Compare commits

...

72 Commits

Author SHA1 Message Date
Joshua Boelter
fefe2fd703 Launch elevated instances via shell:AppFolder (#14637)
This uses `shell:AppsFolder` to launch elevated instances of the app via
`ShellExecuteEx` and `runas` in elevate-shim.exe. The app to launch is
discovered via the `GetCurrentApplicationUserModelId` API.

e.g. `shell:AppsFolder\WindowsTerminalDev_8wekyb3d8bbwe!App`

This will fallback to launching `WindowsTerminal.exe` if it fails to
discover the app user model id to launch.

This also fixes a bug in elevate-shim where the first argument of
WinMain was lost (e.g. `new-tab`).

Curiously, `AppLogic::RunAsUwp()` is never called and
`AppLogic::IsUwp()` is always false when running debug builds locally
(e.g. WindowsTerminalDev). It's not clear if this is an artifact of
development packages or something else.

## Validation Steps Performed

Various manual debug/execution scenarios.

Verified the fallback path by running the unbundled app by extracting
the `CascadiaPackage_0.0.1.0_x64.msix` from the 'drop' build artifact.

Fixes #14501

(cherry picked from commit eab1c239a9)
Service-Card-Id: 87690177
Service-Version: 1.16
2023-01-26 19:47:11 -06:00
Carlos Zamora
7f288414b7 Ensure TermControl is not closing when firing UIA events (#14714)
The `SignalTextChanged` crash seems to be occurring due to the `TermControlAutomationPeer` being destructed by the time the UIA event is actually dispatched. Even though we're already checking if TCAP and TermControl still exist, it could be that the TermControl is being closed as text is being output.

The proposed fix here is to record when the closing process starts and exposing that information directly to the TCAP. If TCAP sees that we're in the process of closing, don't bother sending a UIA event.

Closes #13978

(cherry picked from commit 3dd40791c9)
Service-Card-Id: 87728855
Service-Version: 1.16
2023-01-23 16:57:30 -06:00
Dustin L. Howett
be63f95a08 Remove our dependency on Microsoft.Toolkit.Win32.UI.XamlApplication (#14520)
We originally needed this library (or a separate DLL in our own project)
to handle hooking up the XAML resource loader to the providers that our
application needed. It was introduced in its nascent form in 2019, in a
PR titled "Make XAML files work."

It appears we no longer need it, and the provider hookup is being
handled by our `AppT2` base class override. I've tested this in Windows
10 Vb running unpackaged, and it seems to work totally fine. Crazy.

Removing this dependency saves us a couple hundred kilobytes on disk and
removes one consumer of the App CRT from our package.

(cherry picked from commit 68cce101bc)
2023-01-20 15:56:13 -06:00
Dustin L. Howett
c53b71411c Code sign the contents of the Terminal package (#14710)
Up until now, we have been relying on the catalog signature produced for our MSIX package.
There are some things (Packaged COM, Process Explorer as of 2022) that cannot handle catalog-signed
files. It's easier and safer for us to simply sign all the executables we produce before packaging them.

Unfortunately, we can't do it before we package them. We have to unpack and re-pack our package.

In the future, this will allow us to provide a codesigned distribution that is not in an MSIX package.

TEST=Ran a build and checked out the contents of the package. They were all signed!

Closes #13294
Closes #12695
Closes #9670

(cherry picked from commit 72be9a95af)
Service-Card-Id: 87690424
Service-Version: 1.16
2023-01-20 11:57:20 -06:00
Carlos Zamora
56f9d241d3 Add mutex to keyEvents in TermControlAutomationPeer (#14694)
Some investigation revealed that `_keyEvents` would get a `NULL_POINTER_READ` error. On the main thread, `RecordKeyEvent()` would be called, which mainly updates `_keyEvents`. On the renderer thread, `NotifyNewOutput()` would be called, which starts by iterating through `_keyEvents` and slowly clearing it out. On occasion, these two threads are modifying `_keyEvents` simultaneously, causing a crash.

The fix is to add a mutex on this variable.

Closes #14592

(cherry picked from commit 8e041692b3)
Service-Card-Id: 87649541
Service-Version: 1.16
2023-01-20 11:57:19 -06:00
Mike Griese
471034ba10 Make sure focused tab text color accounts for alpha (#14643)
Basically what it says on the tin. For transparent tabs, we should layer on to the tab row to evaluate what the actual color of the tab will be. We did this for deselected tabs, but not for selected ones.

Gif below.

Closes #14561

(cherry picked from commit 4c7879bfb5)
Service-Card-Id: 87567529
Service-Version: 1.16
2023-01-20 11:57:16 -06:00
Carlos Zamora
bb67c1b02c [WPF] Add TermCore null checks to HwndTerminal (#14678)
Closes #14461

Ran locally. Still works.

(cherry picked from commit dc6d82e9bc)
Service-Card-Id: 87602014
Service-Version: 1.16
2023-01-20 11:57:14 -06:00
Dustin L. Howett
31d4345ea4 Fix an issue where JsonUtils produces a bad error message (#14668)
CascadiaSettings relies on getting a JsonUtils::DeserializationException
from the various JSON Utility functions, and then formatting that into
an error message. Well, DeserializationException tries to include an
object representation in its what() message . . . and generates an
exception trying to do so. CascadiaSettings never gets the
DeserializationException, and displays a weird message.

It's safe to remove the stringification in DeserializationException
because CascadiaSettings was never using it (_and_ because
CascadiaSettings was using an even better version of the same logic.)

Fixes #14373

(cherry picked from commit 239b4d16b9)
Service-Card-Id: 87568498
Service-Version: 1.16
2023-01-13 13:36:58 -06:00
Carlos Zamora
7d401e8293 Introduce PseudoConsoleWindow a11y provider (#14541)
In order to modify the accessibility information for the PseudoConsoleWindow, it needs to have a UIA provider registered. This PR introduces `PseudoConsoleWindowAccessibilityProvider` and registers it as a UIA provider appropriately. The registration process is based on that of the `WindowUiaProvider` for ConHost.

Closes #14385

## Validation Steps Performed
Run Accessibility Insights FastPass on the window. The PseudoConsoleWindow no longer is tagged as missing a name.

(cherry picked from commit 09273be1c8)
Service-Card-Id: 87568605
Service-Version: 1.16
2023-01-13 13:36:56 -06:00
Jie 'Jason' Liu
843195cc89 Fix missing paths when items dropped from archive (#14648)
Grab all paths from `DROPFILES` struct provided in drag event data

`GetStorageItemsAsync()` only giving up to 16 items when items are dropped from any archives
- When this occurs, we should look into `FileDrop` key for a stream of the [`DROPFILES struct`](https://learn.microsoft.com/en-us/windows/win32/shell/clipboard#cf_hdrop)
- This struct contains a null-character delimited string of paths which we can just read out

## Validation Steps Performed
* [X] Unit tests pass locally
* [X] Drag and drop paths work for both archives and non-archives files, folders, shortcuts, etc.

Closes #14628

(cherry picked from commit b7e537e5e7)
Service-Card-Id: 87548939
Service-Version: 1.16
2023-01-13 13:36:53 -06:00
Mike Griese
83d4009589 Add the Theme schema for 1.16 (#14672)
This is just #14666 ported to 1.16. Only diff is that useMica is removed. 

Related to https://github.com/microsoft/terminal/issues/14560
2023-01-12 18:10:38 -06:00
Leonard Hecker
2f1d2ea0d1 Refactor ConsoleProcessList (#14421)
This commit is just a slight refactor of `ConsoleProcessList` which I've noticed
was in a poor shape. It replaces iterators with for-range loops, etc.

Additionally this fixes a bug in `SetConsoleWindowOwner`, where it used to
default to the newest client process instead of the oldest.

Finally, it changes the process container type from a doubly linked list
over to a simple array/vector, because using linked lists for heap allocated
elements felt quite a bit silly. To preserve the previous behavior of
`GetProcessList`, it simply iterates through the vector backwards.

## Validation Steps Performed
* All unit/feature tests pass 
* Launching a TUI application inside pwsh inside cmd
  and exiting kills all 3 applications 

(cherry picked from commit 391abafc2e)
Service-Card-Id: 87207825
Service-Version: 1.16
2022-12-12 17:43:54 -06:00
Leonard Hecker
a7b0fdfbd2 Fix a potential deadlock for PtySignal::SetParent (#14463)
This changeset consists of two parts:
* Refactor `PtySignalInputThread` to move more code from `_InputThread`
  into the various `_Do*` handlers. This allows us to precisely control
  console locking behavior which is the cause of this bug.
* Add the 1-line fix to `_DoSetWindowParent` to unlock the console before
  calling foreign functions (`SetWindowLongPtrW` in this case).

This fix is theoretical in nature, based on a memory dump from an affected user
and most likely fixes: https://developercommunity.visualstudio.com/t/10199439

## Validation Steps Performed
* ConPTY tests complete. 

(cherry picked from commit 3c78e01ab5)
Service-Card-Id: 87207821
Service-Version: 1.16
2022-12-12 17:43:52 -06:00
Dustin L. Howett
0cd9b15451 Give the root PID ownership of the pseudoconsole window (#14196)
This is a partial fix for the Get-Credential issue. While investigating it, I found that the pseudoconsole window is not marked as being "owned" (in NTUSER) by the PID/TID of the console application that is "hosted" "in" it. Doing this does not (and cannot) fix `Get-Credential` failing in DefTerm scenarios.

ConsoleSetWindowOwner is one of the operations that can be done by a conhost to any window, and so the RemoteConsoleControl can call through to the Win32 ConsoleControl to pull it off.

I chose to add SetWindowOwner to the IConsoleControl interface instead of moving ConsoleControl::Control into the interface to reduce the amount of churn and better separate interface responsibilities.

References #14119

(cherry picked from commit 62ffa4ba41)
Service-Card-Id: 87207849
Service-Version: 1.16
2022-12-12 17:43:51 -06:00
Mike Griese
fe4d276fd6 Fix a couple issues with experimental.useBackgroundImageForWindow (#14456)
This fixes two issues with `experimental.useBackgroundImageForWindow` I discovered while looking at #14260

* It looks like the opacity of the whole-window BG image wouldn't hot reload if the path didn't.
* > set useBGForWindow:true, focus a pane with an image, then set it to useBGForWindow:false, and observe a pane with <100 opacity. You'll be able to see the BG image left behind!

These are pretty easy to miss, so I can see how it happened.

I don't think this _technically_ closes that thread, though. Ultimately, I think OP's settings were just wrong (and possible didn't hot-reload). There's another, trickier bit I'm discussing in that thread, that might deserve its own separate follow-up for discussion.

(cherry picked from commit f2eed92345)
Service-Card-Id: 87207792
Service-Version: 1.16
2022-12-12 17:43:50 -06:00
Leonard Hecker
82b63c2574 Wait for clients to exit on ConPTY shutdown (#14282)
#14160 didn't fix #14132 entirely. There seems to be a race condition left
where (on my system) 9 out of 10 times everything works correctly,
but sometimes OpenConsole exits, while pwsh and bash keep running.

My leading theory is that the new code is exiting OpenConsole faster than the
old code. This prevents clients from calling console APIs, etc. causing them
to get stuck. The old code (and new code) calls `ExitProcess` when the ConPTY
pipes break and I think this is wrong: In conhost when you close the window we
only call `CloseConsoleProcessState` via the `WM_CLOSE` event and that's it.
Solution: Remove the call to `RundownAndExit` for ConPTY.

During testing I found that continuously printing text inside msys2 will cause
child processes to only exit slowly one by one every 5 seconds.
This happens because `CloseConsoleProcessState` calls `HandleCtrlEvent` without
holding the console lock. This creates a race condition where most of the time
the console IO thread is the one picking up the `CTRL_CLOSE_EVENT`. But that's
problematic because the `CTRL_CLOSE_EVENT` leads to a `ConsoleControl` call of
type `ConsoleEndTask` which calls back into conhost's IO thread and
so you got the IO thread waiting on itself to respond.
Solution: Don't race conditions.

## Validation Steps Performed
* `Enter-VsDevShell` and close the tab
  Everything exits after 5s 
* Run msys2 bash from within pwsh and close the tab
  Everything exits instantly 
* Run `cat bigfile.txt` and close the tab
  Everything exits instantly 
* Patch `conhost.exe` with `sfpcopy`, as well as `KernelBase.dll`
  with the recent changes to `winconpty`, then launch and exit
  shells and applications via VS Code's terminal 
* On the main branch without this modification remove the call to
  `TriggerTeardown` in `RundownAndExit` (this speeds up the shutdown).
  Run (msys2's) `bash.exe --login` and hold enter and then press Ctrl+Shift+W
  simultaneously. The tab should close and randomly OpenConsole should exit
  early while pwsh/bash keep running. Then retry this with this branch and
  observe how the child processes don't stick around forever anymore. 

(cherry picked from commit b6b1ff8b2c)
Service-Card-Id: 87207832
Service-Version: 1.16
2022-12-12 17:43:49 -06:00
Leonard Hecker
c95552a8c1 Use float throughout ColorFix (#14266)
This is just a quick drive-by improvement. Switching from double to float
roughly doubles performance on a contemporary x86 CPU with `/fp:fast`.

## Validation Steps Performed
* Patch `RenderSettings.hpp` to include `Mode::AlwaysDistinguishableColors`
* Run a color intense application in AtlasEngine and observe CPU usage

(cherry picked from commit bbc14a0baf)
Service-Card-Id: 87207830
Service-Version: 1.16
2022-12-12 17:43:47 -06:00
James Holderness
ee6d3655bb Make sure Terminal state machine always accepts C1 controls (#13969)
When we added support for the `DECAC1` control sequence, which
determines whether `C1` controls are accepted or not, the intention was
that conhost would be making that determination, and Windows Terminal
would always be expected to accept any passed-through `C1` controls.

However, this didn't take into account that a passed-through `RIS`
sequence could end up disabling `DECAC1`, and that would leave Windows
Terminal incapable of processing any `C1` controls. This PR attempts to
fix that oversight.

The `DECAC1` sequence was added in PR #11690, when we disabled `C1`
acceptance by default.

This is a bit of a hack, but I've added a new `AlwaysAcceptC1` mode to
the state machine, which is enabled at startup in the Terminal, and is
never disabled. The parser then just needs to check whether either
`AcceptC1` or `AlwaysAcceptC1` are set.

## Validation Steps Performed

I've manually confirmed the test case in #13968 now works as expected.

Closes #13968

(cherry picked from commit f2b361c146)
Service-Card-Id: 87207767
Service-Version: 1.16
2022-12-12 17:43:46 -06:00
Dustin Howett
dbc30ad741 Revert "Override center on launch setting when position specified on cmdline (#14229)"
This reverts commit c518397fe9.
2022-12-12 17:33:27 -06:00
Hamza Nauman
152740676b Merged PR 8072712: [Git2Git] Fix conhost crash due to cmd.exe launch race
There is a condition which causes the console host process (conhost.exe)
to crash with a `FAIL_FAST` in `WriteCharsLegacy`.

**_Repro Scenario:_** Two conditions need to be met for crash to happen:

1. The `ENABLE_PROCESSED_OUTPUT` console mode needs to be disabled. This
   condition is met through the race condition, explained in the section
   below.
2. We are printing a string where there is a full width character
   (character that requires two spaces on the screen) being printed at
   the edge of the console window. That is, we have one character space
   available, and the character requires 2 spaces.

Running following script (attached to bug) causes a crash:
`for /l %%A in (0, 1, 10000) do start /B C:\test.bat`

The script `test.bat` repeatedly prints a console-width line
with a DBCS character that doesn't fit.

_**Race:**_ Normally, we get into `WriteCharsLegacy` with
`PROCESSED_OUTPUT` enabled. However, during the initialization of a new
CMD session, `cmd!ResetConsoleMode()` is called, which first sets the
output console mode to the value of `curOutputMode` (which is a static
variable initialized to 0) by calling `SetConsoleMode()`, before then
setting it to the desired output mode with processed output enabled:

```c++
void ResetConsoleMode( void )
{
    static DWORD desOutMode = ENABLE_PROCESSED_OUTPUT | /* ... */;

    SetConsoleMode(conOut, curOutputMode); // <------ sets console mode to 0, disabling processed output
    if (GetConsoleMode(conOut, &curOutputMode)) {
        if ((curOutputMode & desOutMode) != desOutMode) {
            curOutputMode |= desOutMode;

            if (!SetConsoleMode(conOut, curOutputMode) && /* ... */) // <----- enables processed output
```

If there is another instance of CMD that is producing output in between
these two `SetConsoleMode()` calls, then we may end up in
`WriteCharsLegacy` with processed output mode disabled.

This fix removes a `FAIL_FAST_IF` that checks for `PROCESSED_OUTPUT`
mode after the initial character processing loop.

Before RS5, this was an `ASSERT()`. This FAIL_FAST was added in RS5 in
PR !1794053 (which changed all `ASSERT`-likes to `FAIL_FAST_IF`.)

We believe this assertion guarded only the "processing" of Backspace,
Tab, CR and LF, and did not expect that we would get out of the
character processing loop with unprocessed glyph characters.  The
`FAIL_FAST` is redundant in this case, as the handlers for the
Backspace, Tab, CR and LF characters we are already checking for
`PROCESSED_OUTPUT`. Therefore, it is safe to remove this `FAIL_FAST`.

It turns out that we *can* exit the loop with unprocessed glyph
characters. In these cases, we don't want to `FAIL_FAST`.

# Validation
* Basic sanity testing to confirm strings are correctly being printed.
* Repro scenario script no longer crashes conhost.exe

Retrieved from https://microsoft.visualstudio.com os.2020 OS official/rs_we_adept_e4d2 eb5d8064dc0f09d8be92efb5e6efa69983f30a3f

Related work items: MSFT-42055103

(cherry picked from commit 86928bb48d)
(cherry picked from commit 788e42f482)
2022-12-12 17:27:22 -06:00
Bharat Dev Burman
bc860a9256 reword en-US value for confirmCloseAllTabs (#14473)
Fixes #14433

(cherry picked from commit 86aa666903)
Service-Card-Id: 87207139
Service-Version: 1.16
2022-12-12 17:24:45 -06:00
Mike Griese
e1fccd8905 Enable vintage opacity on Windows 10 (#14481)
This reverts #11372 and #11285, and brings #11180 to everyone, now that MSFT:37879806 has been serviced to everyone in [KB5011831](https://support.microsoft.com/en-gb/topic/april-25-2022-kb5011831-os-builds-19042-1682-19043-1682-and-19044-1682-preview-fe4ff411-d25a-4185-aabb-8bc66e9dbb6c)[1].

I tested this on my home Win10 laptop that's super old and doesn't have a functioning clock, but it does have that update at the very least.

I don't think we had an issue tracking this?

[1]: I'm pretty sure about this at least

(cherry picked from commit a5c5b8a50e)
Service-Card-Id: 87176746
Service-Version: 1.16
2022-12-12 17:24:43 -06:00
Leonard Hecker
0d130a7397 Harden against resizing down to 0 columns/rows (#14467)
This changeset includes various guards against resizing the terminal down to 0
columns/rows: The 2 `TextBuffer` locations that accept new sizes, as well as
the `HwndTerminal::Refresh` which was the entrypoint causing the issue.

Closes #14404

(cherry picked from commit c5d417fcaf)
Service-Card-Id: 87020511
Service-Version: 1.16
2022-12-12 17:24:42 -06:00
Javier
a23423a98d Added null check before rendering a string from the terminal connection (#14515)
Watson reports show that Visual Studio terminal attempts to render a string that is null causing the renderer to crash.

More specifically, we see "NULL_POINTER_WRITE_c0000005_PublicTerminalCore.dll!TextBuffer::WriteLine" with the following stack:
PublicTerminalCore!TextBuffer::WriteLine+0x1da
PublicTerminalCore!TextBuffer::Write+0x191
PublicTerminalCore!Microsoft::Terminal::Core::Terminal::_WriteBuffer+0x1d3
PublicTerminalCore!Microsoft::Terminal::Core::Terminal::PrintString+0x9
PublicTerminalCore!TerminalDispatch::PrintString+0x22
PublicTerminalCore!Microsoft::Console::VirtualTerminal::OutputStateMachineEngine::ActionPrintString+0x42
PublicTerminalCore!Microsoft::Console::VirtualTerminal::StateMachine::ProcessString+0x123
PublicTerminalCore!TerminalSendOutput+0x68
Microsoft_DotNet_MSBuildSdkResolver!DomainBoundILStubClass.IL_STUB_PInvoke(IntPtr, System.String)+0x8f
Microsoft_Terminal_Wpf!Microsoft.Terminal.Wpf.TerminalContainer.Connection_TerminalOutput(System.Object, Microsoft.Terminal.Wpf.TerminalOutputEventArgs)+0x20
Microsoft_VisualStudio_Terminal_Implementation!Microsoft.VisualStudio.Terminal.TerminalWindowBase+<>c__DisplayClass59_0+<<BeginProcessingPtyData>b__0>d.MoveNext()+0x55f

Internal bug: [Bug 1614709](https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1614709): [Watson] crash64: NULL_POINTER_WRITE_c0000005_PublicTerminalCore.dll!TextBuffer::WriteLine

Added a null check before PInvoking TerminalSendOutput.

Validated locally that the check prevents null strings from rendering.

(cherry picked from commit 79c47f64a2)
Service-Card-Id: 87204854
Service-Version: 1.16
2022-12-12 17:23:35 -06:00
Junyoung Lee
b73718a42a Add the setting "confirmCloseAllTabs" to SUI (#14419)
This commit adds the setting "confirmCloseAllTabs" to SUI.
The setting was added to the Interactions pane of Global Settings.

Closes #14413
Closes #14033

(cherry picked from commit 437b5ac595)
Service-Card-Id: 87207138
Service-Version: 1.16
2022-12-12 17:23:11 -06:00
Ben Constable
4938b92a1c [schema] Update allowed types for startingDirectory (#14408)
Update the schema to support null.

## PR Checklist
* [x] Closes #14299
* [x] Schema updated.

(cherry picked from commit feed768b3f)
Service-Card-Id: 87207135
Service-Version: 1.16
2022-12-12 17:23:10 -06:00
Carlos Zamora
d19b96289a Apply AutoProps to TextBox settings in SUI (#14178)
We already were setting the automation properties on the expander, however, we were not setting it on the content when an expander was present. This change applies the automation properties to both the expander and the child content (i.e. TextBox).

Closes #13827

(cherry picked from commit 62b34cf6f7)
Service-Card-Id: 87207144
Service-Version: 1.16
2022-12-12 17:23:09 -06:00
PankajBhojwani
c0999305fc Respect the "/max" parameter when starting console apps with defterm enabled (#14222)
## Summary of the Pull Request

- Pipe the `ShowWindow` value through to `ConptyConnection`
- When `TerminalPage` receives the new connection, it checks the `ShowWindow` value and maximizes *IF* there were no other pre-existing tabs (in glomming mode, we don't want to maximize sessions that did not ask for it)

## References
#12154

## PR Checklist
* [ ] Closes #xxx
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [ ] Schema updated.
* [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx

## Detailed Description of the Pull Request / Additional comments
This is just a temporary solution until we change our defterm handoff process. Because of the way the process currently works, we have no way of knowing that the connection has requested the window to be maximized until after we have already started a terminal session. This means that we have to manually maximize the window upon receiving the connection, instead of having the session _start_ maximized, as it probably should.

## Validation Steps Performed
`start /max python` with defterm enabled opens up python in a maximized WT window

(cherry picked from commit 85ca8f556c)
Service-Card-Id: 87207152
Service-Version: 1.16
2022-12-12 17:23:07 -06:00
Ian O'Neill
c518397fe9 Override center on launch setting when position specified on cmdline (#14229)
Override the center on launch setting when a position is specified on the commandline.

## Validation Steps Performed
1. Set center on launch in the SUI.
2. Run `wtd` - the new window is centered.
3. Run `wtd --pos 100,200` - the new window is positioned at (100,200).

Closes #14176

(cherry picked from commit 42befa7b58)
Service-Card-Id: 87207151
Service-Version: 1.16
2022-12-12 17:23:06 -06:00
Rose
5ed748c3bf Update to XAML 2.7.3 (#14123)
And the prerelease version of it

(cherry picked from commit 11ad04754d)
Service-Card-Id: 87207161
Service-Version: 1.16
2022-12-12 17:23:05 -06:00
Rose
5b474b6468 Update libpopcnt to 2.5 (#14140)
(cherry picked from commit d7e24ad6d0)
Service-Card-Id: 87207159
Service-Version: 1.16
2022-12-12 17:23:04 -06:00
Rose
47ba4b2c3d Update IntervalTree.h dependency (#14148)
This was the last update since 2021

(cherry picked from commit a63f060f72)
Service-Card-Id: 87207154
Service-Version: 1.16
2022-12-12 17:23:02 -06:00
Rose
9657a88820 Update jsoncpp from 1.9.3 to 1.9.5 (#14122)
(cherry picked from commit 00cdacc96b)
Service-Card-Id: 87207157
Service-Version: 1.16
2022-12-12 17:23:01 -06:00
Dustin Howett
b65ffdb281 Merged PR 8189936: [Git2Git] Lift an optional check out of RefreshRowIDs loop to fix a crash
In the most recent compiler ingestion into Windows ("LKG14"), we found
that this particular construction--checking an optional for a value
during this range-for loop--resulted in bad code generation.

When optimized, it generates code that looks effectively like this:

```c++
if (!newRowWidth.has_value()) {
	while (true) {
		// do the row stuff...
		++it;
	}
}
```

The loop never exits, and `_RefreshRowIDs` walks off the end of the
buffer. Whoops.

This commit fixes that issue by tricking the optimizer to go another
way. Leonard tells me it's harmless to call `Resize` a bunch of times,
even if it's a no-op, so I trust that this change results in the right
outcome with none of the crashing.

Fixes MSFT-41456525

Retrieved from https://microsoft.visualstudio.com os.2020 OS official/rs_we_adept_e4d2 c2b3697c867bddf5660da8b222e99ff4bfd1ea5b

(cherry picked from commit 3c104440a8)
2022-12-12 17:22:23 -06:00
Mike Griese
785704f9b7 Find out how often are people actually using marks, Themes (#14356)
Let's find out!

* [x] This is all the current bullets in #14324. I'm going to leave that open till we signoff on the release.

(cherry picked from commit 52cc523ed2)
Service-Card-Id: 86660872
Service-Version: 1.16
2022-12-01 15:44:32 -06:00
Leonard Hecker
0fe29b7599 Initialize all members of Terminal (#14345)
The following members were not initialized during construction:
* `CursorType _defaultCursorShape`
* `bool _suppressApplicationTitle`
* `bool _bracketedPasteMode`
* `size_t _hyperlinkPatternId`
* `SelectionExpansion _multiClickSelectionMode`
* `til::CoordType _scrollbackLines`

Unlike gcc and clang, MSVC is fairly tame when it comes to removing code
tainted by undefined behavior, so the most likely affect this had is that
we were reading uninitialized memory.

Related to #14129.

(cherry picked from commit a798a603e1)
Service-Card-Id: 86603221
Service-Version: 1.16
2022-12-01 15:44:32 -06:00
Leonard Hecker
18e4a824cf AtlasEngine: Fix a heap overflow bug (#14275)
`TextBuffer` is buggy and allows a `Trailing` `DbcsAttribute` to be written
into the first column. Since other code then blindly assumes that there's a
preceding `Leading` character, we'll get called with a X coordinate of -1.
This issue will be fixed by #13626 and this commit fixes it in the meantime.

Additionally fixes an unimportant crash when the window height is 0px,
because it was annoying during testing and doesn't hurt to be fixed.

## Validation Steps Performed
* Run a stress test that prints random Unicode at random positions
* Resize the window furiously at the same time
* Doesn't crash / fail-fast 

(cherry picked from commit bb4711de54)
Service-Card-Id: 86353783
Service-Version: 1.16
2022-12-01 15:44:32 -06:00
PankajBhojwani
c1729bcc09 Reorder the color chips grid in the color schemes page (#14223)
XAML has an issue in windows 10 where `Width="*"` does not work properly
inside the `DataTemplate` for a `ListView`. Because of this, the color
scheme list view items looked very strange in windows 10 (see #14187).

Thanks to that, we thought up a few new designs for the color schemes
page and selected a new one that blends the color chips with a region
that shows the foreground and background color with the text preview.

Closes #14187

(cherry picked from commit 23a02c5218)
Service-Card-Id: 86518549
Service-Version: 1.16
2022-12-01 15:44:32 -06:00
Leonard Hecker
e192d543ed Skip DECPS/MIDI output on Ctrl+C/Break (#14214)
Silent MIDI notes can be used to seemingly deny a user's input for long
durations (multiple minutes). This commit improves the situation by ignoring
all DECPS sequences for a second when Ctrl+C/Ctrl+Break is pressed.

Additionally it fixes a regression introduced in 666c446:
When we close a tab we need to unblock/shutdown `MidiAudio` early,
so that `ConptyConnection::Close()` can run down as fast as possible.

* In pwsh in Windows Terminal 1.16 run ``while ($True) { echo "`e[3;8;3,~" }``
  * Ctrl+C doesn't do anything 
  * Closing the tab doesn't do anything 
* With these modifications in Windows Terminal:
  * Ctrl+C stops the output 
  * Closing the tab completes instantly 
* With these modifications in OpenConsole:
  * Ctrl+C stops the output 
  * Closing the window completes instantly 

(cherry picked from commit b4fce27203)
Service-Card-Id: 86518585
Service-Version: 1.16
2022-12-01 15:44:32 -06:00
Jeroen B
2449f274bd Disable acrylic material (temporarily) when opacity is set to 100% (#14193)
If the opacity is set to 100%, the background becomes solid instead of 'fully opaque acrylic'. If the opacity is below 100% the acrylic material is re-enabled (depending on the user's settings).

## Validation Steps Performed

I updated two unit tests to reflect the change in behavior and manually tested the transition from <100% opacity to 100% opacity (and vice versa) on win11.

Steps:
1. Start with 100% opacity and acrylic material enabled.
2. Decrease opacity and observe acrylic effect.
3. Increase opacity back to 100% and disable the acrylic effect.
4. Decrease opacity and notice that acrylic effect is no longer there.

Closes #12880

(cherry picked from commit 8ea3cb9972)
Service-Card-Id: 86444093
Service-Version: 1.16
2022-12-01 15:44:32 -06:00
Carlos Zamora
8a9da742c8 Remove redundant tooltips from settings UI (#14244)
## Summary of the Pull Request
This removes all of the redundant tooltips from the settings UI. Since all of the settings are added through the SettingsContainer, it's a pretty simple change.

Closes #14184

## Validation Steps Performed
- [X] hover over all settings in the settings UI
- [X] hover over all entries in the SUI nav view

(cherry picked from commit 3eaa781499)
Service-Card-Id: 86390069
Service-Version: 1.16
2022-12-01 15:44:32 -06:00
Leonard Hecker
cd367e6411 AtlasEngine: Block chars done right-er (#14099)
This commit makes the following improvements:
* Only adjust block characters that come from fallback fonts. This ensures
  that the glyphs of the chosen font all look exactly as they were designed.
* When adjusting the size, use the fallback font's full block glyph U+2588
  to determine the size that the given glyph should have.

Closes #14098

## Validation Steps Performed
* Print `UTF-8-demo.txt` in Consolas.
* All block glyphs look uniform. 

(cherry picked from commit 97abc3df1d)
Service-Card-Id: 86159056
Service-Version: 1.16
2022-12-01 15:44:32 -06:00
Dustin L. Howett
f29c3e3598 Migrate spelling-0.0.21 changes from main 2022-10-15 02:58:03 -05:00
Dustin L. Howett
0dccbaca58 Fix the Release build ProxyStubClsids from #13570 (#14225)
These were wrong.

(cherry picked from commit 1f19ed0cd2)
Service-Card-Id: 86230901
Service-Version: 1.16
2022-10-17 12:24:30 -05:00
Dustin L. Howett
afdd628ac7 Stop freeing BSTRs that do not belong to us (#14224)
The `BSTR` arguments originate from COM calls who own them.
Found via AppVerifier.

(cherry picked from commit 2a5ce4900f)
Service-Card-Id: 86230696
Service-Version: 1.16
2022-10-17 12:24:28 -05:00
Dustin L. Howett
6b4a3e813d Disallow a window waiting on system() to block DefTerm startup (#14195)
We'll just ping the window and give it a chance to respond before we
bunk with it.

Fixes #14131

(cherry picked from commit ab04067e49)
Service-Card-Id: 86230024
Service-Version: 1.16
2022-10-14 16:51:03 -05:00
Dustin L. Howett
cfb8f66658 OpenHere: stop failing if there's no site... (#14211)
It cannot be known why there is no site.
We should at least not crash.

Fixes MSFT-41571451

(cherry picked from commit 18e4e22394)
Service-Card-Id: 86206546
Service-Version: 1.16
2022-10-14 16:12:38 -05:00
Bjorn Neergaard
d2d3600855 Fix a missing entry for intenseTextStyle in the Profile schema (#14210)
Fix a missing entry in the JSON schema for `intenseTextStyle`.

The JSON schema was missing an entry in the Profile section for
`intenseTextStyle`. I have added it as it appears in AppearanceConfig.
Note that this is currently duplicated in the schema -- however, this is
the pattern used already in Profile as AppearanceConfig entries have
alternate descriptions (and I have updated the description in that
section to make it clear it applies to unfocused terminals).
Longer-term, it likely makes sense to consolidate all entires into
ApperanceConfig and rely on the description for the `unfocusedApperance`
object/the name of the object to make the limited scope of those keys
clear, so that Profile can simply extend ApperanceConfig and the
duplication in the schema can be reduced.

## Validation Steps Performed
Validation with schema verifying tools including VS Code.

Partially addresses #13387

(cherry picked from commit 33cb0eb05f)
Service-Card-Id: 86228743
Service-Version: 1.16
2022-10-14 16:12:37 -05:00
Dustin L. Howett
ef7b8497e2 Pipe DirectKey events into TerminalPage for Alt+Space (#14221)
This pull request operates on the same theory as #14217, but at a lower
level. Carlos and I discovered that TerminalPage *already* has an
action-dispatching key preview handler, and that my implementation of
`IDirectKeyListener` handles focus-tree bubbling mostly correctly.

Because of that discovery, we learned we could move the
`IDirectKeyListener` into TerminalPage itself and not have to complicate
the SUI or the Command Palette with the DirectKey interface.

Validation:
When bound to Alt+Space, the system menu works in the command palette,
the settings UI, and in read-only panes.

Fixes #11970
Closes #14217
Fixes MSFT-41390832

(cherry picked from commit d319d479c7)
Service-Card-Id: 86228470
Service-Version: 1.16
2022-10-14 16:12:35 -05:00
Leonard Hecker
d3a66ff297 Fix a deadlock during ConPTY shutdown (#14160)
Problem:
* Calling `RundownAndExit` tries to flush out the last frame from `VtEngine`
* `VtEngine` indirectly calls `RundownAndExit` if the pipe is gone via `VtIo`
* `RundownAndExit` is called by other parts of OpenConsole
* `RundownAndExit` must be `[[noreturn]]` for most parts of OpenConsole
* `VtIo` itself has a mutex ensuring orderly shutdown
* In short, doing a thread safe orderly shutdown requires us to hold both,
  a lock in `RundownAndExit` and `VtIo` at the same time, but while other parts
  need a blocking `RundownAndExit`, `VtIo` needs a non-blocking one
* Refactoring the code to use optionally non-blocking `RundownAndExit`
  requires refactoring and might prove to be just as buggy

Solution:
* Simply don't call `RundownAndExit` in `VtEngine` at all
* In case the write pipe breaks:
  * `VtEngine` will close the handle
  * The client should notice that their read pipe is broken and
    close their write pipe sooner or later
  * Once we notice that our read pipe is broken, we call `RundownAndExit`
  * `RundownAndExit` might call back into `VtEngine` but
    without a pipe it won't do anything
* In case the read pipe breaks or any other part calls `RundownAndExit`:
  * We call `RundownAndExit`
  * `RundownAndExit` might call back into `VtEngine` and depending on whether
    the write pipe is broken or not it will simply write into it or ignore it

Closes #14132
Pretty sure this also applies to #1810

## Validation Steps Performed
* Open 5 tabs and run MSYS2's `bash --login` in each of them
* `Enter-VsDevShell` in another tab
* Close window
* 5 tab processes are killed instantly, 1 after ~3s 
* Replace conhost with OpenConsole via sfpcopy
* Launch Dozens of Git Bash tabs in VS Code
* Close them randomly
* Remaining ones still work, processes are gone 

(cherry picked from commit 1774cfd843)
Service-Card-Id: 86174637
Service-Version: 1.16
2022-10-13 18:19:14 -05:00
Dustin L. Howett
a9cf3d78f3 Add a maximum OSC 8 URI length of 2MB following iTerm2 (#14198)
c0b2f488c1

Unlike iTerm2, we're not planning on making it configurable.

This commit also adds a max length of 1024 characters on the "display URI" that we pass up to XAML, so as to not inundate the UI.

Fixes #14200

(cherry picked from commit 07201d6cd1)
Service-Card-Id: 86182618
Service-Version: 1.16
2022-10-13 17:02:27 -05:00
Jeroen B
100dbc5038 Fix duplication issue for unfocused tabs (#13964)
Instead of using the currently focused tab when an unfocused tab is duplicated, the `_MakePane(...)` function now uses an optional source tab argument that points to the correct tab being duplicated.

## Validation Steps Performed

Manually tested on multiple tabs with different profiles. Performed steps:

* Construct at least two tabs with different profiles.
* Select `Duplicate Tab` option from the dropdown menu of the unfocused tab.
* Verify that the new tab has the same profile as the tab it was duplicated from.

Closes #13942

(cherry picked from commit 8f08bb04d0)
Service-Card-Id: 86159037
Service-Version: 1.16
2022-10-13 17:02:26 -05:00
Carlos Zamora
e376f8c99f Make SUI breadcrumb readable by screen readers (#14180)
The breadcrumbs in the SUI were not readable by screen readers because they are represented as a button with a text block inside of it. Turns out, if you make the DataTemplate's item `IStringable` (meaning it has a `ToString()`), it all magically works! Allowing the screen reader to read the button as text.

Closes #13826

(cherry picked from commit 30046dd4a7)
Service-Card-Id: 86158952
Service-Version: 1.16
2022-10-13 17:02:23 -05:00
Jonathan Meier
926c8e08e0 Fix clipped progress ring in tab when tab title is too long (#14167)
It turns out that the negative margin for the progress ring is causing
the clipping in case the tab title gets too long:

43dbbd590f/src/cascadia/TerminalApp/TabHeaderControl.xaml (L18-L27)

The negative margin was introduced in #8113 because the progress ring is
supposed to replace the tab icon but the `TabView` still reserves space
even if no icon is set (see
https://github.com/microsoft/terminal/pull/8133#issuecomment-739098014).
However, it is not actually the `TabView` reserving space even when
there is no icon, but a workaround for a crash in the
`IconPathConverter` that returns a `BitmapIconSource` with a `nullptr`
source instead of a `nullptr` `IconSource`:

43dbbd590f/src/cascadia/TerminalSettingsModel/IconPathConverter.cpp (L143-L154)

The workaround in `IconPathConverter` could probably be removed as I did
not find any instance where it is still used in a way that could trigger
the mentioned crash, but I did not dare to just remove it as I do not
know enough about the code by far. Hence, I opted to just locally
instantiate the `IconSource` with a `nullptr` directly in `TerminalTab`.

Fixes #8910

(cherry picked from commit 21a9c55752)
Service-Card-Id: 86209056
Service-Version: 1.16
2022-10-13 17:02:21 -05:00
Carlos Zamora
c82a577529 [wpf] Add UIA events (#14097)
Adds UIA events to the WPF control for the following items:
- selection changed
- text changed (and output)
- cursor changed

### Automation Peer
Similar to the architecture of the UWP TermControl, we added a
`HwndTerminalAutomationPeer` which acts as the
`TermControlAutomationPeer` in UWP. However, we don't need a XAML
wrapper here, so really we just need it to inherit from
`TermControlUiaProvider` (the `ITextProvider` implementation shared
across conhost and WT) and `IUiaEventDispatcher` (the event dispatching
interface that is responsible for signaling the screen reader that
something has changed).

### Removing the local echo
As with WT, we need to record key events to remove the local echo. These
recorded events are matched up with the output text. Each sequential
match is removed in the output text so that it's not read by the screen
reader.

### Detecting what to send events for
As with WT, a `UiaEngine` was added to the renderer and it is set up
when a UIA client is detected. WT would normally stop sending events
when focus was lost from the control. We do the same here.

### Automation properties
`TermControlUiaProvider` was upgraded to support property values. Such
properties include class name and control type. These align with those
set in `TermControlAutomationPeer`. Realistically, those should point to
these, but that requires a lot more work and a localization burden
(because we need to move the localized word "terminal").

`HwndTerminalAutomationPeer` takes this a step further and overrides the
class name to be `WPFTermControl`. This allows screen readers to provide
special handling for the `WPFTermControl` vs the UWP term control since
they will be updating at different speeds.

### Build fixes
To build the WPF test app, I had to mess with the dependencies a little
bit. Really just add the atlas engine and uia renderer to the build
steps.

### HwndTerminal initialization
The initialization order with `WM_NCCREATE` was changed to match that of
Windows Terminal (BaseWindow/IslandWindow). This is safer now. I also
removed the `static` window because it was unnecessary.

### Handling `WM_GETOBJECT`
WPF's HwndHost likes to mark the `WM_GETOBJECT` message as handled to
force the usage of the WPF automation peer. We now explicitly mark it as
not handled and don't return an automation peer. This forces the message
to go down to the HwndTerminal where we return terminal's UiaProvider.

### Remove TermControl layer from UIA tree
TermContol (the top-most layer in the UIA tree) would pop up and not do
anything. This PR also overrides the automation peer at that layer and
marks IsContentElement/IsControlElement=false (the equivalent to
AccessibilityView=Raw). This makes the layer only appear in the UIA tree
if you are using the raw view (i.e. you know what you're doing and you
want to see each individual layer even if you can't directly interact
with it).

## Validation Steps Performed
Tested with Narrator/NVDA using WpfTerminalTestNetCore project in our
repo.
- [X] New output is read out (not just key events, but also other output
  text)
- [X] Local echo does not occur (i.e. pressing 'A' should only read 'A'
  once, not twice [key event and rendered letter]).
- [X] selection events are read out properly
- [X] cursor change events are read out properly (tested with text
  cursor indicator preview in Settings App > Accessibility > Text
  Cursor)

NOTE: test this with Release builds. Debug builds may be too slow and
not read out properly

Closes #12642

(cherry picked from commit 5608cf15a3)
Service-Card-Id: 86081129
Service-Version: 1.16
2022-10-06 18:36:28 -05:00
Dustin Howett
ce26137128 Delay-load dsound.dll in MidiAudio
Closes #14104

(cherry-picked from commit fba4e227f0)
2022-10-04 13:17:54 -05:00
Dustin L. Howett
b150a98fc0 Reject illegal paths in OSC 9;9 (#14093)
Paths that contain illegal path components will be dropped
in the dispatcher.

(cherry picked from commit fc0ef37977)
Service-Card-Id: 85900830
Service-Version: 1.16
2022-09-28 11:47:58 -05:00
Leonard Hecker
4af96a2133 AtlasEngine: Partially revert glyph scaling changes (#14085)
This change fixes issues with certain fonts that draw _way_ outside the advance
width/height black box and expect to remain centered on the baseline.

## Validation Steps Performed
* Use MesloLGM Nerd Font
* Print U+E0B0
* Ensure it's centered, even if it's cut off 

(cherry picked from commit 2de475b36a)
Service-Card-Id: 85876935
Service-Version: 1.16
2022-09-28 11:47:57 -05:00
Leonard Hecker
47f1167af2 AtlasEngine: Fix uneven baselines when scaling glyphs (#14039)
This commit changes the glyph scale algorithm to prefer aligning glyphs to
their baseline. This improves the visual appearance of simulated italic glyphs.
However wide Emojis in narrow cells now look slightly worse without centering.

Closes #13987

## Validation Steps Performed
* Use FiraCode which has no italic variant and instead uses simulated italics
* Write italic text
* Baseline is consistent 

(cherry picked from commit 97dc5c8d75)
Service-Card-Id: 85767343
Service-Version: 1.16
2022-09-21 17:30:29 -05:00
Leonard Hecker
45310d77a8 Fix potential lags/deadlocks during tab close (#14041)
`ConptyClosePseudoConsole` blocks until OpenConsole exits.
This is problematic for the changes in 666c446, which stopped calling that
function on a background thread to solve a race condition. This commit fixes
the potential lags/deadlocks from waiting on OpenConsole's exit, by adding
`ConptyClosePseudoConsoleNoWait` which only closes the IO handles and allows
OpenConsole to exit naturally. This uncovered another potential deadlock
in `ServiceLocator::RundownAndExit` which might call itself recursively.

Closes #14032

## Validation Steps Performed
* Print tons of text and concurrently close the tab.
  Tab closes, OpenConsole/pwsh exits instantly 
* Use `Enter-VsDevShell` and close the tab.
  Tab closes instantly, OpenConsole/pwsh exits after ~5 seconds 

(cherry picked from commit 274bdb31da)
Service-Card-Id: 85767341
Service-Version: 1.16
2022-09-21 17:30:28 -05:00
Dustin L. Howett
3717fae714 OpenHere: Replace explorer window lookup code w/ site lookup (#14048)
When we first introduced the shell extension, it didn't work properly
for some folders (such as the Desktop, or perhaps any "background"
click) due to a bug in Windows. We worked around that bug with the help
of an awesome community member, who contributed code that would pull up
the topmost Explorer window and query its location.

That Windows bug was eventually fixed, but we still had trouble with
items appearing correctly. On Windows 11, the Open in Terminal menu item
appears and disappears at random when you right-click the desktop, but
it always appears when you right-click a folder. It sometimes appears
for Quick Access, even though it shouldn't.

We tried to fix that in #13206, but the fix caused more issues than it
solved. We reverted it for 1.15 and 1.16.

At the end of the day, it turns out that getting the path from the
toplevel explorer window is fragile. Fortunately, the shell does offer
us a way to get that information: the site chain.

This pull request replaces GetPathFromExplorer() with an implementation
of `IObjectWithSite`, which allows us to use the site chain to look up
from whence a context menu request was initiated. It also makes item
lookup generally more robust.

*  Tested on Windows 11
  *  Desktop
  *  Folder Background
  *  Folder Selected
  *  Quick Access (does not appear)
  *  This PC (does not appear)
*  Tested on Windows 10
  *  Desktop
  *  Folder Background
  *  Folder Selected
  *  Quick Access (does not appear)
  *  This PC (does not appear)

References #13206
References #13523
Closes #12578

Co-authored-by: John Lueders <johnlue@microsoft.com>
(cherry picked from commit 5027c8031d)
Service-Card-Id: 85788409
Service-Version: 1.16
2022-09-21 12:43:45 -05:00
Leonard Hecker
9d0346c2b3 AtlasEngine: Fix cursor invalidation (#14038)
There's a different behavior regarding cursors between conhost and Windows
Terminal. In case of the latter we don't necessarily call `PaintCursor`
during cursor movement, because the cursor blinker never stops "blinking".

Closes #14028

## Validation Steps Performed
* Enter text until after the line wraps
* Hold backspace until the line unwraps
* No leftover cursor on the second line 

(cherry picked from commit 08096b2343)
Service-Card-Id: 85767353
Service-Version: 1.16
2022-09-21 11:15:07 -05:00
Leonard Hecker
8876417f87 Fix font size rounding in the settings UI (#14040)
This fixes an issue with c51bb3a, where some fractional font
sizes are displayed as something like 13.600000000001.

Closes #14024

## Validation Steps Performed
* Enter a font size of 13.6 and save
* NumberBox displays "13.6" 

(cherry picked from commit f79276b21b)
Service-Card-Id: 85740785
Service-Version: 1.16
2022-09-21 11:15:06 -05:00
Leonard Hecker
9310db572d AtlasEngine: Fix bugs around bitmap font rendering (#14014)
This commit fixes several issues:
* Some fonts set a line-gap even though they behave as if they
  don't want any line-gaps. Since Terminals don't really have
  any gaps anyways, it'll now not be taken into account anymore.
* Center alignment breaks bitmap glyphs which expect left-alignment.
* Automatic "opsz" axis makes Terminus TTF's italic glyphs look quite
  weird. I disabled this feature as we might not need it anyways.

A complete fix depends on #14013
Closes #14006

## Validation Steps Performed
* Use Terminus TTF at 13.5pt
* Print UTF-8-demo.txt
* No gaps between block characters 

(cherry picked from commit bea13bddf1)
Service-Card-Id: 85767355
Service-Version: 1.16
2022-09-21 11:15:05 -05:00
Dustin L. Howett
9ec3e799ed Regenerate CodepointWidthDetector from Unicode 15.0 (#14001)
Closes #13999

(cherry picked from commit 88c6d7ff5b)
Service-Card-Id: 85767362
Service-Version: 1.16
2022-09-21 11:15:04 -05:00
Leonard Hecker
73ea629c18 Add support for fractional font sizes (#14013)
After this commit a user may specify fractional font sizes.
Support was only implemented for AtlasEngine however.
DxEngine continues to use rounded (integer) font sizes.

Closes #6678

## Validation Steps Performed
* Install a bitmap font that requires fractional font sizes
  (e.g. Terminus TTF, https://files.ax86.net/terminus-ttf/)
* Set font size to something integer (e.g. 14pt)
  Glyphs are blurry 
* Set font size to something fractional (e.g. 13.5pt)
  Glyphs are crisp 

(cherry picked from commit c51bb3a7a6)
Service-Card-Id: 85708971
Service-Version: 1.16
2022-09-16 17:39:20 -05:00
Leonard Hecker
8f013d7ae8 Stop DoSing users with renderer errors (#13995)
If a rendering engine constantly throws error we'll effectively
denial-of-service our users by drowning them in warning popups.
This commit fixes the issue by limiting the retries in all cases.

Issue found in: #13985

## Validation Steps Performed
* Add a `THROW_HR(E_INVALIDARG);` in `AtlasEngine::StartPaint()`
* Launch Windows Terminal
* Only one warning popup shows up 
* Rendering is disabled until one clicks "resume" 

(cherry picked from commit 81e2bc98d1)
Service-Card-Id: 85653502
Service-Version: 1.16
2022-09-16 11:31:43 -05:00
Leonard Hecker
c2c5f410f9 AtlasEngine: Fix a crash when drawing double width rows (#13966)
The `TileHashMap` refresh via `makeNewest()` in `StartPaint()` depends
on us filling the entire `cellGlyphMapping` row with valid data.
This commit makes sure to initialize the `cellGlyphMapping` buffer.
Additionally it clears the rest of the row with whitespace
until proper `LineRendition` support is added.

Closes #13962

## Validation Steps Performed
* vttest's "Test of double-sized characters" stops crashing 
* No weird leftover characters 

(cherry picked from commit 16aa79d78d)
Service-Card-Id: 85653281
Service-Version: 1.16
2022-09-16 11:31:41 -05:00
Leonard Hecker
5e9147e994 AtlasEngine: Properly detect shader model 4 support (#13994)
Direct3D 10.0 and 10.1 only have optional support for shader model 4.
This commit fixes our assumption that it's always present by checking
`ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x` first.

Closes #13985

## Validation Steps Performed
* Set feature level to 10.1 via `dxcpl`
* `CheckFeatureSupport` is called and doesn't throw 

(cherry picked from commit e2b2d9b92c)
Service-Card-Id: 85653388
Service-Version: 1.16
2022-09-16 11:31:39 -05:00
Mårten Rånge
b899d49a26 Relax shader strictness in RELEASE mode (#13998)
Disables strictness and warnings as errors for custom pixel shaders in
RELEASE. Windows terminal is not telling the user why the shader won't
compile which makes it very frustrating for the shader hacker.

After trying the recent preview none of my shaders loaded anymore in
Windows Terminal Preview which made me very sad. I had no idea what was
wrong with them. After cloning the git repo, building it, fighting an
issue that prevent DEBUG SDK from being used I finally was able to
identify some issues that were blocking my shaders.

> error X3556: integer modulus may be much slower, try using uints if possible.
> error X4000: use of potentially uninitialized variable (rayCylinder)

While the first one is a good warning I don't think it is an error and
the tools I use didn't flag it so was hard to know.

The second one I was staring at the code and was unable to identify what
exactly was causing the issues, I fumbled with the code a few times and
just felt the fun drain away.

IMHO: I want it to be fun to develop shaders for windows terminal.
Fighting invisible errors are not fun. I am not after building
production shaders for Windows Terminal, I want some cool effects. So
while I am as a .NET developer always runs with Warning as errors I
don't think it's the right option here. Especially since Windows
Terminal doesn't tell what is the problem.

However, I understand if the shaders you ship with Windows Terminal
should be free of errors and silly mistakes, so I kept the stricter
setting in DEBUG mode.

## Validation Steps Performed

Loaded Windows Terminal in RELEASE and DEBUG mode and validated that
RELEASE mode had reduced strictness but DEBUG retained the previous more
restrictive mode.

(cherry picked from commit b4b6636b49)
Service-Card-Id: 85660397
Service-Version: 1.16
2022-09-16 11:31:38 -05:00
Dustin L. Howett
b73e39ce17 vPack: fix submit branch, add github token from consvc (#13959)
Our Windows branch name changed, and I took this opportunity to resolve
an issue where vpack builds would occasionally fail due to GitHub rate
limiting the Azure DevOps IP addresses.

(cherry picked from commit 3958c938af)
Service-Card-Id: 85567589
Service-Version: 1.16
2022-09-09 13:30:40 -05:00
Dustin Howett
bccd97257e PGO: train 1.16 separately 2022-09-09 12:28:56 -05:00
188 changed files with 4358 additions and 3258 deletions

View File

@@ -6,6 +6,7 @@ File | Purpose | Format | Info
[reject.txt](reject.txt) | Remove words from the dictionary (after allow) | grep pattern matching whole dictionary words | [reject](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-reject)
[excludes.txt](excludes.txt) | Files to ignore entirely | perl regular expression | [excludes](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-excludes)
[patterns/*.txt](patterns/) | Patterns to ignore from checked lines | perl regular expression (order matters, first match wins) | [patterns](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-patterns)
[candidate.patterns](candidate.patterns) | Patterns that might be worth adding to [patterns.txt](patterns.txt) | perl regular expression with optional comment block introductions (all matches will be suggested) | [candidates](https://github.com/check-spelling/check-spelling/wiki/Feature:-Suggest-patterns)
[line_forbidden.patterns](line_forbidden.patterns) | Patterns to flag in checked lines | perl regular expression (order matters, first match wins) | [patterns](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-patterns)
[expect/*.txt](expect.txt) | Expected words that aren't in the dictionary | one word per line (sorted, alphabetically) | [expect](https://github.com/check-spelling/check-spelling/wiki/Configuration#expect)
[advice.md](advice.md) | Supplement for GitHub comment when unrecognized words are found | GitHub Markdown | [advice](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-advice)

View File

@@ -21,7 +21,7 @@ See the `README.md` in each directory for more information.
:microscope: You can test your commits **without** *appending* to a PR by creating a new branch with that extra change and pushing it to your fork. The [check-spelling](https://github.com/marketplace/actions/check-spelling) action will run in response to your **push** -- it doesn't require an open pull request. By using such a branch, you can limit the number of typos your peers see you make. :wink:
<details><summary>:clamp: If the flagged items are false positives</summary>
<details><summary>If the flagged items are :exploding_head: false positives</summary>
If items relate to a ...
* binary file (or some other file you wouldn't want to check at all).

View File

@@ -1,7 +1,7 @@
admins
allcolors
apc
Apc
apc
breadcrumb
breadcrumbs
bsd
@@ -14,8 +14,8 @@ CMMI
copyable
cybersecurity
dalet
dcs
Dcs
dcs
dialytika
dje
downside
@@ -34,10 +34,12 @@ gantt
gcc
geeksforgeeks
ghe
github
gje
godbolt
hostname
hostnames
https
hyperlink
hyperlinking
hyperlinks
@@ -54,9 +56,11 @@ Llast
llvm
Lmid
locl
lol
lorem
Lorigin
maxed
minimalistic
mkmk
mnt
mru
@@ -80,6 +84,7 @@ runtimes
shcha
slnt
Sos
ssh
timeline
timelines
timestamped
@@ -88,6 +93,7 @@ tokenizes
tonos
toolset
tshe
ubuntu
uiatextrange
UIs
und
@@ -96,5 +102,7 @@ versioned
vsdevcmd
We'd
wildcards
XBox
YBox
yeru
zhe

View File

@@ -32,10 +32,10 @@ DERR
dlldata
DNE
DONTADDTORECENT
DWMWA
DWORDLONG
DWMSBT
DWMWA
DWMWA
DWORDLONG
endfor
ENDSESSION
enumset
@@ -110,8 +110,8 @@ memchr
memicmp
MENUCOMMAND
MENUDATA
MENUITEMINFOW
MENUINFO
MENUITEMINFOW
mmeapi
MOUSELEAVE
mov
@@ -158,8 +158,8 @@ rcx
REGCLS
RETURNCMD
rfind
roundf
ROOTOWNER
roundf
RSHIFT
SACL
schandle
@@ -211,6 +211,7 @@ UPDATEINIFILE
userenv
USEROBJECTFLAGS
Viewbox
virtualalloc
wcsstr
wcstoui
winmain

View File

@@ -0,0 +1,523 @@
# marker to ignore all code on line
^.*/\* #no-spell-check-line \*/.*$
# marker for ignoring a comment to the end of the line
// #no-spell-check.*$
# patch hunk comments
^\@\@ -\d+(?:,\d+|) \+\d+(?:,\d+|) \@\@ .*
# git index header
index [0-9a-z]{7,40}\.\.[0-9a-z]{7,40}
# cid urls
(['"])cid:.*?\g{-1}
# data url in parens
\(data:[^)]*?(?:[A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,})[^)]*\)
# data url in quotes
([`'"])data:.*?(?:[A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,}).*\g{-1}
# data url
data:[-a-zA-Z=;:/0-9+]*,\S*
# mailto urls
mailto:[-a-zA-Z=;:/?%&0-9+@.]{3,}
# magnet urls
magnet:[?=:\w]+
# magnet urls
"magnet:[^"]+"
# obs:
"obs:[^"]*"
# The `\b` here means a break, it's the fancy way to handle urls, but it makes things harder to read
# In this examples content, I'm using a number of different ways to match things to show various approaches
# asciinema
\basciinema\.org/a/[0-9a-zA-Z]+
# apple
\bdeveloper\.apple\.com/[-\w?=/]+
# Apple music
\bembed\.music\.apple\.com/fr/playlist/usr-share/[-\w.]+
# appveyor api
\bci\.appveyor\.com/api/projects/status/[0-9a-z]+
# appveyor project
\bci\.appveyor\.com/project/(?:[^/\s"]*/){2}builds?/\d+/job/[0-9a-z]+
# Amazon
# Amazon
\bamazon\.com/[-\w]+/(?:dp/[0-9A-Z]+|)
# AWS S3
\b\w*\.s3[^.]*\.amazonaws\.com/[-\w/&#%_?:=]*
# AWS execute-api
\b[0-9a-z]{10}\.execute-api\.[-0-9a-z]+\.amazonaws\.com\b
# AWS ELB
\b\w+\.[-0-9a-z]+\.elb\.amazonaws\.com\b
# AWS SNS
\bsns\.[-0-9a-z]+.amazonaws\.com/[-\w/&#%_?:=]*
# AWS VPC
vpc-\w+
# While you could try to match `http://` and `https://` by using `s?` in `https?://`, sometimes there
# YouTube url
\b(?:(?:www\.|)youtube\.com|youtu.be)/(?:channel/|embed/|user/|playlist\?list=|watch\?v=|v/|)[-a-zA-Z0-9?&=_%]*
# YouTube music
\bmusic\.youtube\.com/youtubei/v1/browse(?:[?&]\w+=[-a-zA-Z0-9?&=_]*)
# YouTube tag
<\s*youtube\s+id=['"][-a-zA-Z0-9?_]*['"]
# YouTube image
\bimg\.youtube\.com/vi/[-a-zA-Z0-9?&=_]*
# Google Accounts
\baccounts.google.com/[-_/?=.:;+%&0-9a-zA-Z]*
# Google Analytics
\bgoogle-analytics\.com/collect.[-0-9a-zA-Z?%=&_.~]*
# Google APIs
\bgoogleapis\.(?:com|dev)/[a-z]+/(?:v\d+/|)[a-z]+/[-@:./?=\w+|&]+
# Google Storage
\b[-a-zA-Z0-9.]*\bstorage\d*\.googleapis\.com(?:/\S*|)
# Google Calendar
\bcalendar\.google\.com/calendar(?:/u/\d+|)/embed\?src=[@./?=\w&%]+
\w+\@group\.calendar\.google\.com\b
# Google DataStudio
\bdatastudio\.google\.com/(?:(?:c/|)u/\d+/|)(?:embed/|)(?:open|reporting|datasources|s)/[-0-9a-zA-Z]+(?:/page/[-0-9a-zA-Z]+|)
# The leading `/` here is as opposed to the `\b` above
# ... a short way to match `https://` or `http://` since most urls have one of those prefixes
# Google Docs
/docs\.google\.com/[a-z]+/(?:ccc\?key=\w+|(?:u/\d+|d/(?:e/|)[0-9a-zA-Z_-]+/)?(?:edit\?[-\w=#.]*|/\?[\w=&]*|))
# Google Drive
\bdrive\.google\.com/(?:file/d/|open)[-0-9a-zA-Z_?=]*
# Google Groups
\bgroups\.google\.com/(?:(?:forum/#!|d/)(?:msg|topics?|searchin)|a)/[^/\s"]+/[-a-zA-Z0-9$]+(?:/[-a-zA-Z0-9]+)*
# Google Maps
\bmaps\.google\.com/maps\?[\w&;=]*
# Google themes
themes\.googleusercontent\.com/static/fonts/[^/\s"]+/v\d+/[^.]+.
# Google CDN
\bclients2\.google(?:usercontent|)\.com[-0-9a-zA-Z/.]*
# Goo.gl
/goo\.gl/[a-zA-Z0-9]+
# Google Chrome Store
\bchrome\.google\.com/webstore/detail/[-\w]*(?:/\w*|)
# Google Books
\bgoogle\.(?:\w{2,4})/books(?:/\w+)*\?[-\w\d=&#.]*
# Google Fonts
\bfonts\.(?:googleapis|gstatic)\.com/[-/?=:;+&0-9a-zA-Z]*
# Google Forms
\bforms\.gle/\w+
# Google Scholar
\bscholar\.google\.com/citations\?user=[A-Za-z0-9_]+
# Google Colab Research Drive
\bcolab\.research\.google\.com/drive/[-0-9a-zA-Z_?=]*
# GitHub SHAs (api)
\bapi.github\.com/repos(?:/[^/\s"]+){3}/[0-9a-f]+\b
# GitHub SHAs (markdown)
(?:\[`?[0-9a-f]+`?\]\(https:/|)/(?:www\.|)github\.com(?:/[^/\s"]+){2,}(?:/[^/\s")]+)(?:[0-9a-f]+(?:[-0-9a-zA-Z/#.]*|)\b|)
# GitHub SHAs
\bgithub\.com(?:/[^/\s"]+){2}[@#][0-9a-f]+\b
# GitHub wiki
\bgithub\.com/(?:[^/]+/){2}wiki/(?:(?:[^/]+/|)_history|[^/]+(?:/_compare|)/[0-9a-f.]{40,})\b
# githubusercontent
/[-a-z0-9]+\.githubusercontent\.com/[-a-zA-Z0-9?&=_\/.]*
# githubassets
\bgithubassets.com/[0-9a-f]+(?:[-/\w.]+)
# gist github
\bgist\.github\.com/[^/\s"]+/[0-9a-f]+
# git.io
\bgit\.io/[0-9a-zA-Z]+
# GitHub JSON
"node_id": "[-a-zA-Z=;:/0-9+]*"
# Contributor
\[[^\]]+\]\(https://github\.com/[^/\s"]+\)
# GHSA
GHSA(?:-[0-9a-z]{4}){3}
# GitLab commit
\bgitlab\.[^/\s"]*/\S+/\S+/commit/[0-9a-f]{7,16}#[0-9a-f]{40}\b
# GitLab merge requests
\bgitlab\.[^/\s"]*/\S+/\S+/-/merge_requests/\d+/diffs#[0-9a-f]{40}\b
# GitLab uploads
\bgitlab\.[^/\s"]*/uploads/[-a-zA-Z=;:/0-9+]*
# GitLab commits
\bgitlab\.[^/\s"]*/(?:[^/\s"]+/){2}commits?/[0-9a-f]+\b
# binanace
accounts.binance.com/[a-z/]*oauth/authorize\?[-0-9a-zA-Z&%]*
# bitbucket diff
\bapi\.bitbucket\.org/\d+\.\d+/repositories/(?:[^/\s"]+/){2}diff(?:stat|)(?:/[^/\s"]+){2}:[0-9a-f]+
# bitbucket repositories commits
\bapi\.bitbucket\.org/\d+\.\d+/repositories/(?:[^/\s"]+/){2}commits?/[0-9a-f]+
# bitbucket commits
\bbitbucket\.org/(?:[^/\s"]+/){2}commits?/[0-9a-f]+
# bit.ly
\bbit\.ly/\w+
# bitrise
\bapp\.bitrise\.io/app/[0-9a-f]*/[\w.?=&]*
# bootstrapcdn.com
\bbootstrapcdn\.com/[-./\w]+
# cdn.cloudflare.com
\bcdnjs\.cloudflare\.com/[./\w]+
# circleci
\bcircleci\.com/gh(?:/[^/\s"]+){1,5}.[a-z]+\?[-0-9a-zA-Z=&]+
# gitter
\bgitter\.im(?:/[^/\s"]+){2}\?at=[0-9a-f]+
# gravatar
\bgravatar\.com/avatar/[0-9a-f]+
# ibm
[a-z.]*ibm\.com/[-_#=:%!?~.\\/\d\w]*
# imgur
\bimgur\.com/[^.]+
# Internet Archive
\barchive\.org/web/\d+/(?:[-\w.?,'/\\+&%$#_:]*)
# discord
/discord(?:app\.com|\.gg)/(?:invite/)?[a-zA-Z0-9]{7,}
# Disqus
\bdisqus\.com/[-\w/%.()!?&=_]*
# medium link
\blink\.medium\.com/[a-zA-Z0-9]+
# medium
\bmedium\.com/\@?[^/\s"]+/[-\w]+
# microsoft
\b(?:https?://|)(?:(?:download\.visualstudio|docs|msdn2?|research)\.microsoft|blogs\.msdn)\.com/[-_a-zA-Z0-9()=./%]*
# powerbi
\bapp\.powerbi\.com/reportEmbed/[^"' ]*
# vs devops
\bvisualstudio.com(?::443|)/[-\w/?=%&.]*
# microsoft store
\bmicrosoft\.com/store/apps/\w+
# mvnrepository.com
\bmvnrepository\.com/[-0-9a-z./]+
# now.sh
/[0-9a-z-.]+\.now\.sh\b
# oracle
\bdocs\.oracle\.com/[-0-9a-zA-Z./_?#&=]*
# chromatic.com
/\S+.chromatic.com\S*[")]
# codacy
\bapi\.codacy\.com/project/badge/Grade/[0-9a-f]+
# compai
\bcompai\.pub/v1/png/[0-9a-f]+
# mailgun api
\.api\.mailgun\.net/v3/domains/[0-9a-z]+\.mailgun.org/messages/[0-9a-zA-Z=@]*
# mailgun
\b[0-9a-z]+.mailgun.org
# /message-id/
/message-id/[-\w@./%]+
# Reddit
\breddit\.com/r/[/\w_]*
# requestb.in
\brequestb\.in/[0-9a-z]+
# sched
\b[a-z0-9]+\.sched\.com\b
# Slack url
slack://[a-zA-Z0-9?&=]+
# Slack
\bslack\.com/[-0-9a-zA-Z/_~?&=.]*
# Slack edge
\bslack-edge\.com/[-a-zA-Z0-9?&=%./]+
# Slack images
\bslack-imgs\.com/[-a-zA-Z0-9?&=%.]+
# shields.io
\bshields\.io/[-\w/%?=&.:+;,]*
# stackexchange -- https://stackexchange.com/feeds/sites
\b(?:askubuntu|serverfault|stack(?:exchange|overflow)|superuser).com/(?:questions/\w+/[-\w]+|a/)
# Sentry
[0-9a-f]{32}\@o\d+\.ingest\.sentry\.io\b
# Twitter markdown
\[\@[^[/\]:]*?\]\(https://twitter.com/[^/\s"')]*(?:/status/\d+(?:\?[-_0-9a-zA-Z&=]*|)|)\)
# Twitter hashtag
\btwitter\.com/hashtag/[\w?_=&]*
# Twitter status
\btwitter\.com/[^/\s"')]*(?:/status/\d+(?:\?[-_0-9a-zA-Z&=]*|)|)
# Twitter profile images
\btwimg\.com/profile_images/[_\w./]*
# Twitter media
\btwimg\.com/media/[-_\w./?=]*
# Twitter link shortened
\bt\.co/\w+
# facebook
\bfburl\.com/[0-9a-z_]+
# facebook CDN
\bfbcdn\.net/[\w/.,]*
# facebook watch
\bfb\.watch/[0-9A-Za-z]+
# dropbox
\bdropbox\.com/sh?/[^/\s"]+/[-0-9A-Za-z_.%?=&;]+
# ipfs protocol
ipfs://[0-9a-z]*
# ipfs url
/ipfs/[0-9a-z]*
# w3
\bw3\.org/[-0-9a-zA-Z/#.]+
# loom
\bloom\.com/embed/[0-9a-f]+
# regex101
\bregex101\.com/r/[^/\s"]+/\d+
# figma
\bfigma\.com/file(?:/[0-9a-zA-Z]+/)+
# freecodecamp.org
\bfreecodecamp\.org/[-\w/.]+
# image.tmdb.org
\bimage\.tmdb\.org/[/\w.]+
# mermaid
\bmermaid\.ink/img/[-\w]+|\bmermaid-js\.github\.io/mermaid-live-editor/#/edit/[-\w]+
# Wikipedia
\ben\.wikipedia\.org/wiki/[-\w%.#]+
# gitweb
[^"\s]+/gitweb/\S+;h=[0-9a-f]+
# HyperKitty lists
/archives/list/[^@/]+\@[^/\s"]*/message/[^/\s"]*/
# lists
/thread\.html/[^"\s]+
# list-management
\blist-manage\.com/subscribe(?:[?&](?:u|id)=[0-9a-f]+)+
# kubectl.kubernetes.io/last-applied-configuration
"kubectl.kubernetes.io/last-applied-configuration": ".*"
# pgp
\bgnupg\.net/pks/lookup[?&=0-9a-zA-Z]*
# Spotify
\bopen\.spotify\.com/embed/playlist/\w+
# Mastodon
\bmastodon\.[-a-z.]*/(?:media/|\@)[?&=0-9a-zA-Z_]*
# scastie
\bscastie\.scala-lang\.org/[^/]+/\w+
# images.unsplash.com
\bimages\.unsplash\.com/(?:(?:flagged|reserve)/|)[-\w./%?=%&.;]+
# pastebin
\bpastebin\.com/[\w/]+
# heroku
\b\w+\.heroku\.com/source/archive/\w+
# quip
\b\w+\.quip\.com/\w+(?:(?:#|/issues/)\w+)?
# badgen.net
\bbadgen\.net/badge/[^")\]'\s]+
# statuspage.io
\w+\.statuspage\.io\b
# media.giphy.com
\bmedia\.giphy\.com/media/[^/]+/[\w.?&=]+
# tinyurl
\btinyurl\.com/\w+
# getopts
\bgetopts\s+(?:"[^"]+"|'[^']+')
# ANSI color codes
(?:\\(?:u00|x)1b|\x1b)\[\d+(?:;\d+|)m
# URL escaped characters
\%[0-9A-F][A-F]
# IPv6
\b(?:[0-9a-fA-F]{0,4}:){3,7}[0-9a-fA-F]{0,4}\b
# c99 hex digits (not the full format, just one I've seen)
0x[0-9a-fA-F](?:\.[0-9a-fA-F]*|)[pP]
# Punycode
\bxn--[-0-9a-z]+
# sha
sha\d+:[0-9]*[a-f]{3,}[0-9a-f]*
# sha-... -- uses a fancy capture
(['"]|&quot;)[0-9a-f]{40,}\g{-1}
# hex runs
\b[0-9a-fA-F]{16,}\b
# hex in url queries
=[0-9a-fA-F]*?(?:[A-F]{3,}|[a-f]{3,})[0-9a-fA-F]*?&
# ssh
(?:ssh-\S+|-nistp256) [-a-zA-Z=;:/0-9+]{12,}
# PGP
\b(?:[0-9A-F]{4} ){9}[0-9A-F]{4}\b
# GPG keys
\b(?:[0-9A-F]{4} ){5}(?: [0-9A-F]{4}){5}\b
# Well known gpg keys
.well-known/openpgpkey/[\w./]+
# uuid:
\b[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}\b
# hex digits including css/html color classes:
(?:[\\0][xX]|\\u|[uU]\+|#x?|\%23)[0-9_a-fA-FgGrR]*?[a-fA-FgGrR]{2,}[0-9_a-fA-FgGrR]*(?:[uUlL]{0,3}|u\d+)\b
# integrity
integrity="sha\d+-[-a-zA-Z=;:/0-9+]{40,}"
# https://www.gnu.org/software/groff/manual/groff.html
# man troff content
\\f[BCIPR]
# '
\\\(aq
# .desktop mime types
^MimeTypes?=.*$
# .desktop localized entries
^[A-Z][a-z]+\[[a-z]+\]=.*$
# Localized .desktop content
Name\[[^\]]+\]=.*
# IServiceProvider
\bI(?=(?:[A-Z][a-z]{2,})+\b)
# crypt
"\$2[ayb]\$.{56}"
# scrypt / argon
\$(?:scrypt|argon\d+[di]*)\$\S+
# Input to GitHub JSON
content: "[-a-zA-Z=;:/0-9+]*="
# Python stringprefix / binaryprefix
# Note that there's a high false positive rate, remove the `?=` and search for the regex to see if the matches seem like reasonable strings
(?<!')\b(?:B|BR|Br|F|FR|Fr|R|RB|RF|Rb|Rf|U|UR|Ur|b|bR|br|f|fR|fr|r|rB|rF|rb|rf|u|uR|ur)'(?:[A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,})
# Regular expressions for (P|p)assword
\([A-Z]\|[a-z]\)[a-z]+
# JavaScript regular expressions
# javascript test regex
/.*/[gim]*\.test\(
# javascript match regex
\.match\(/[^/\s"]*/[gim]*\s*
# javascript match regex
\.match\(/\\[b].*?/[gim]*\s*\)(?:;|$)
# javascript regex
^\s*/\\[b].*/[gim]*\s*(?:\)(?:;|$)|,$)
# javascript replace regex
\.replace\(/[^/\s"]*/[gim]*\s*,
# Go regular expressions
regexp?\.MustCompile\(`[^`]*`\)
# sed regular expressions
sed 's/(?:[^/]*?[a-zA-Z]{3,}[^/]*?/){2}
# go install
go install(?:\s+[a-z]+\.[-@\w/.]+)+
# kubernetes pod status lists
# https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase
\w+(?:-\w+)+\s+\d+/\d+\s+(?:Running|Pending|Succeeded|Failed|Unknown)\s+
# kubectl - pods in CrashLoopBackOff
\w+-[0-9a-f]+-\w+\s+\d+/\d+\s+CrashLoopBackOff\s+
# kubernetes object suffix
-[0-9a-f]{10}-\w{5}\s
# posthog secrets
posthog\.init\((['"])phc_[^"',]+\g{-1},
# xcode
# xcodeproject scenes
(?:Controller|ID|id)="\w{3}-\w{2}-\w{3}"
# xcode api botches
customObjectInstantitationMethod
# font awesome classes
\.fa-[-a-z0-9]+
# Update Lorem based on your content (requires `ge` and `w` from https://github.com/jsoref/spelling; and `review` from https://github.com/check-spelling/check-spelling/wiki/Looking-for-items-locally )
# grep '^[^#].*lorem' .github/actions/spelling/patterns.txt|perl -pne 's/.*i..\?://;s/\).*//' |tr '|' "\n"|sort -f |xargs -n1 ge|perl -pne 's/^[^:]*://'|sort -u|w|sed -e 's/ .*//'|w|review -
# Warning, while `(?i)` is very neat and fancy, if you have some binary files that aren't proper unicode, you might run into:
## Operation "substitution (s///)" returns its argument for non-Unicode code point 0x1C19AE (the code point will vary).
## You could manually change `(?i)X...` to use `[Xx]...`
## or you could add the files to your `excludes` file (a version after 0.0.19 should identify the file path)
# Lorem
(?:\w|\s|[,.])*\b(?i)(?:amet|consectetur|cursus|dolor|eros|ipsum|lacus|libero|ligula|lorem|magna|neque|nulla|suscipit|tempus)\b(?:\w|\s|[,.])*
# Non-English
[a-zA-Z]*[ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź][a-zA-Z]{3}[a-zA-ZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź]*
# French
# This corpus only had capital letters, but you probably want lowercase ones as well.
\b[LN]'+[a-z]{2,}\b
# latex
\\(?:n(?:ew|ormal|osub)|r(?:enew)|t(?:able(?:of|)|he|itle))(?=[a-z]+)
# the negative lookahead here is to allow catching 'templatesz' as a misspelling
# but to otherwise recognize a Windows path with \templates\foo.template or similar:
\\(?:necessary|r(?:eport|esolve[dr]?|esult)|t(?:arget|emplates?))(?![a-z])
# ignore long runs of a single character:
\b([A-Za-z])\g{-1}{3,}\b
# Note that the next example is no longer necessary if you are using
# to match a string starting with a `#`, use a character-class:
[#]backwards
# version suffix <word>v#
(?:(?<=[A-Z]{2})V|(?<=[a-z]{2}|[A-Z]{2})v)\d+(?:\b|(?=[a-zA-Z_]))
# Compiler flags (Scala)
(?:^|[\t ,>"'`=(])-J-[DPWXY](?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,})
# Compiler flags
#(?:^|[\t ,"'`=(])-[DPWXYLlf](?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,})
# Compiler flags (linker)
,-B
# curl arguments
\b(?:\\n|)curl(?:\s+-[a-zA-Z]{1,2}\b)*(?:\s+-[a-zA-Z]{3,})(?:\s+-[a-zA-Z]+)*
# set arguments
\bset(?:\s+-[abefimouxE]{1,2})*\s+-[abefimouxE]{3,}(?:\s+-[abefimouxE]+)*
# tar arguments
\b(?:\\n|)g?tar(?:\.exe|)(?:(?:\s+--[-a-zA-Z]+|\s+-[a-zA-Z]+|\s[ABGJMOPRSUWZacdfh-pr-xz]+\b)(?:=[^ ]*|))+
# tput arguments -- https://man7.org/linux/man-pages/man5/terminfo.5.html -- technically they can be more than 5 chars long...
\btput\s+(?:(?:-[SV]|-T\s*\w+)\s+)*\w{3,5}\b
# macOS temp folders
/var/folders/\w\w/[+\w]+/(?:T|-Caches-)/

View File

@@ -2,14 +2,14 @@
(?:(?i)\.png$)
(?:^|/)(?i)COPYRIGHT
(?:^|/)(?i)LICEN[CS]E
(?:^|/)3rdparty/
(?:^|/)dirs$
(?:^|/)go\.mod$
(?:^|/)go\.sum$
(?:^|/)package(?:-lock|)\.json$
(?:^|/)sources(?:|\.dep)$
(?:^|/)vendor/
ignore$
SUMS$
\.a$
\.ai$
\.avi$
\.bmp$
@@ -20,6 +20,8 @@ SUMS$
\.crt$
\.csr$
\.dll$
\.docx?$
\.drawio$
\.DS_Store$
\.eot$
\.eps$
@@ -31,6 +33,7 @@ SUMS$
\.icns$
\.ico$
\.jar$
\.jks$
\.jpeg$
\.jpg$
\.key$
@@ -41,6 +44,7 @@ SUMS$
\.mod$
\.mp3$
\.mp4$
\.o$
\.ocf$
\.otf$
\.pbxproj$
@@ -48,22 +52,41 @@ SUMS$
\.pem$
\.png$
\.psd$
\.pyc$
\.runsettings$
\.s$
\.sig$
\.so$
\.svg$
\.svgz$
\.svgz?$
\.tar$
\.tgz$
\.tiff?$
\.ttf$
\.vsdx$
\.wav$
\.webm$
\.webp$
\.woff
\.woff2?$
\.xcf$
\.xls
\.xlsx?$
\.xpm$
\.yml$
\.zip$
^\.github/actions/spelling/
^\.github/fabricbot.json$
^\.gitignore$
^\Q.git-blame-ignore-revs\E$
^\Q.github/workflows/spelling.yml\E$
^\Qdoc/reference/windows-terminal-logo.ans\E$
^\Qsamples/ConPTY/EchoCon/EchoCon/EchoCon.vcxproj.filters\E$
^\Qsrc/host/exe/Host.EXE.vcxproj.filters\E$
^\Qsrc/host/ft_host/chafa.txt\E$
^\Qsrc/tools/closetest/CloseTest.vcxproj.filters\E$
^\XamlStyler.json$
^build/config/
^consolegit2gitfilters\.json$
^dep/
@@ -90,12 +113,5 @@ SUMS$
^src/tools/U8U16Test/(?:fr|ru|zh)\.txt$
^src/types/ut_types/UtilsTests.cpp$
^tools/ReleaseEngineering/ServicingPipeline.ps1$
^\.github/actions/spelling/
^\.github/fabricbot.json$
^\.gitignore$
^\Q.github/workflows/spelling.yml\E$
^\Qsamples/ConPTY/EchoCon/EchoCon/EchoCon.vcxproj.filters\E$
^\Qsrc/host/exe/Host.EXE.vcxproj.filters\E$
^\Qsrc/host/ft_host/chafa.txt\E$
^\Qsrc/tools/closetest/CloseTest.vcxproj.filters\E$
^\XamlStyler.json$
ignore$
SUMS$

View File

@@ -5,26 +5,19 @@ AAAAAABBBBBBCCC
AAAAABBBBBBCCC
abcd
abcd
abcde
abcdef
ABCDEFG
ABCDEFGH
ABCDEFGHIJ
abcdefghijk
ABCDEFGHIJKLMNO
abcdefghijklmnop
ABCDEFGHIJKLMNOPQRST
abcdefghijklmnopqrstuvwxyz
ABCG
ABE
abf
BBBBB
BBBBBBBB
BBBBBBBBBBBBBBDDDD
BBBBBCCC
BBBBCCCCC
BBGGRR
CCE
EFG
EFGh
QQQQQQQQQQABCDEFGHIJ

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,3 @@
http
www
WCAG
winui
appshellintegration

View File

@@ -1,3 +1,11 @@
# reject `m_data` as there's a certain OS which has evil defines that break things if it's used elsewhere
# \bm_data\b
# If you have a framework that uses `it()` for testing and `fit()` for debugging a specific test,
# you might not want to check in code where you were debugging w/ `fit()`, in which case, you might want
# to use this:
#\bfit\(
# s.b. GitHub
\bGithub\b
@@ -16,6 +24,12 @@
# s.b. greater than
\bgreater then\b
# s.b. into
#\sin to\s
# s.b. opt-in
\sopt in\s
# s.b. less than
\bless then\b
@@ -27,10 +41,22 @@
\b[Nn]o[nt][- ]existent\b
# s.b. preexisting
[Pp]re-existing
[Pp]re[- ]existing
# s.b. preempt
[Pp]re[- ]empt\b
# s.b. preemptively
[Pp]re-emptively
[Pp]re[- ]emptively
# s.b. reentrancy
[Rr]e[- ]entrancy
# s.b. reentrant
[Rr]e[- ]entrant
# s.b. workaround(s)
#\bwork[- ]arounds?\b
# Reject duplicate words
\s([A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,})\s\g{-1}\s

View File

@@ -27,13 +27,68 @@ ROY\sG\.\sBIV
# Python stringprefix / binaryprefix
\b(?:B|BR|Br|F|FR|Fr|R|RB|RF|Rb|Rf|U|UR|Ur|b|bR|br|f|fR|fr|r|rB|rF|rb|rf|u|uR|ur)'
# Automatically suggested patterns
# hit-count: 3831 file-count: 582
# IServiceProvider
\bI(?=(?:[A-Z][a-z]{2,})+\b)
# hit-count: 71 file-count: 35
# Compiler flags
(?:^|[\t ,"'`=(])-[D](?=[A-Z]{2,}|[A-Z][a-z])
(?:^|[\t ,"'`=(])-[X](?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,})
# hit-count: 41 file-count: 28
# version suffix <word>v#
(?:(?<=[A-Z]{2})V|(?<=[a-z]{2}|[A-Z]{2})v)\d+(?:\b|(?=[a-zA-Z_]))
# hit-count: 20 file-count: 9
# hex runs
\b[0-9a-fA-F]{16,}\b
# hit-count: 10 file-count: 7
# uuid:
\b[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}\b
# hit-count: 4 file-count: 4
# mailto urls
mailto:[-a-zA-Z=;:/?%&0-9+@.]{3,}
# hit-count: 4 file-count: 1
# ANSI color codes
(?:\\(?:u00|x)1b|\x1b)\[\d+(?:;\d+|)m
# hit-count: 2 file-count: 1
# latex
\\(?:n(?:ew|ormal|osub)|r(?:enew)|t(?:able(?:of|)|he|itle))(?=[a-z]+)
# hit-count: 1 file-count: 1
# hex digits including css/html color classes:
(?:[\\0][xX]|\\u|[uU]\+|#x?|\%23)[0-9_a-fA-FgGrR]*?[a-fA-FgGrR]{2,}[0-9_a-fA-FgGrR]*(?:[uUlL]{0,3}|u\d+)\b
# hit-count: 1 file-count: 1
# Non-English
[a-zA-Z]*[ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź][a-zA-Z]{3}[a-zA-ZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź]*
# hit-count: 1 file-count: 1
# French
# This corpus only had capital letters, but you probably want lowercase ones as well.
\b[LN]'+[a-z]{2,}\b
# acceptable duplicates
# ls directory listings
[-bcdlpsw](?:[-r][-w][-sx]){3}\s+\d+\s+(\S+)\s+\g{-1}\s+\d+\s+
# C/idl types + English ...
\s(Guid|long|LONG|that) \g{-1}\s
# javadoc / .net
(?:\@(?:groupname|param)|(?:public|private)(?:\s+static|\s+readonly)*)\s+(\w+)\s+\g{-1}\s
(?:[\\@](?:groupname|param)|(?:public|private)(?:\s+static|\s+readonly)*)\s+(\w+)\s+\g{-1}\s
# Commit message -- Signed-off-by and friends
^\s*(?:(?:Based-on-patch|Co-authored|Helped|Mentored|Reported|Reviewed|Signed-off)-by|Thanks-to): (?:[^<]*<[^>]*>|[^<]*)\s*$
# Autogenerated revert commit message
^This reverts commit [0-9a-f]{40}\.$
# vtmode
--vtmode\s+(\w+)\s+\g{-1}\s

View File

@@ -1,31 +1,12 @@
benefitting
occurences?
Sorce
^attache$
^attacher$
^attachers$
benefitting
occurences?
^dependan.*
^oer$
^spae$
^spae-man$
^spaebook$
^spaecraft$
^spaed$
^spaedom$
^spaeing$
^spaeings$
^spaeman$
^spaer$
^Spaerobee$
^spaes$
^spaewife$
^spaewoman$
^spaework$
^spaewright$
Sorce
^[Ss]pae.*
^untill$
^untilling$
^wether$
^wether.*
^wethers$
^wetherteg$
^[Ss]pae.*

View File

@@ -1,10 +1,57 @@
# spelling.yml is blocked per https://github.com/check-spelling/check-spelling/security/advisories/GHSA-g86g-chm8-7r2p
name: Spell checking
# Comment management is handled through a secondary job, for details see:
# https://github.com/check-spelling/check-spelling/wiki/Feature%3A-Restricted-Permissions
#
# `jobs.comment-push` runs when a push is made to a repository and the `jobs.spelling` job needs to make a comment
# (in odd cases, it might actually run just to collapse a commment, but that's fairly rare)
# it needs `contents: write` in order to add a comment.
#
# `jobs.comment-pr` runs when a pull_request is made to a repository and the `jobs.spelling` job needs to make a comment
# or collapse a comment (in the case where it had previously made a comment and now no longer needs to show a comment)
# it needs `pull-requests: write` in order to manipulate those comments.
# Updating pull request branches is managed via comment handling.
# For details, see: https://github.com/check-spelling/check-spelling/wiki/Feature:-Update-expect-list
#
# These elements work together to make it happen:
#
# `on.issue_comment`
# This event listens to comments by users asking to update the metadata.
#
# `jobs.update`
# This job runs in response to an issue_comment and will push a new commit
# to update the spelling metadata.
#
# `with.experimental_apply_changes_via_bot`
# Tells the action to support and generate messages that enable it
# to make a commit to update the spelling metadata.
#
# `with.ssh_key`
# In order to trigger workflows when the commit is made, you can provide a
# secret (typically, a write-enabled github deploy key).
#
# For background, see: https://github.com/check-spelling/check-spelling/wiki/Feature:-Update-with-deploy-key
on:
pull_request_target:
push:
branches: ["**"]
tags-ignore: ["**"]
branches:
- "**"
tags-ignore:
- "**"
pull_request_target:
branches:
- "**"
tags-ignore:
- "**"
types:
- 'opened'
- 'reopened'
- 'synchronize'
issue_comment:
types:
- 'created'
jobs:
spelling:
@@ -24,23 +71,64 @@ jobs:
steps:
- name: check-spelling
id: spelling
uses: check-spelling/check-spelling@v0.0.20
uses: check-spelling/check-spelling@v0.0.21
with:
suppress_push_for_open_pull_request: 1
checkout: true
check_file_names: 1
spell_check_this: check-spelling/spell-check-this@prerelease
post_comment: 0
use_magic_file: 1
extra_dictionary_limit: 10
extra_dictionaries:
cspell:software-terms/src/software-terms.txt
cspell:python/src/python/python-lib.txt
cspell:node/node.txt
cspell:cpp/src/stdlib-c.txt
cspell:cpp/src/stdlib-cpp.txt
cspell:fullstack/fullstack.txt
cspell:filetypes/filetypes.txt
cspell:html/html.txt
cspell:cpp/src/compiler-msvc.txt
cspell:python/src/common/extra.txt
cspell:powershell/powershell.txt
cspell:aws/aws.txt
cspell:cpp/src/lang-keywords.txt
cspell:npm/npm.txt
cspell:dotnet/dotnet.txt
cspell:python/src/python/python.txt
cspell:css/css.txt
cspell:cpp/src/stdlib-cmath.txt
check_extra_dictionaries: ''
comment:
name: Report
comment-push:
name: Report (Push)
# If your workflow isn't running on push, you can remove this job
runs-on: ubuntu-latest
needs: spelling
permissions:
contents: write
pull-requests: write
if: (success() || failure()) && needs.spelling.outputs.followup && github.event_name != 'push'
if: (success() || failure()) && needs.spelling.outputs.followup && github.event_name == 'push'
steps:
- name: comment
uses: check-spelling/check-spelling@v0.0.20
uses: check-spelling/check-spelling@v0.0.21
with:
checkout: true
spell_check_this: check-spelling/spell-check-this@prerelease
task: ${{ needs.spelling.outputs.followup }}
comment-pr:
name: Report (PR)
# If you workflow isn't running on pull_request*, you can remove this job
runs-on: ubuntu-latest
needs: spelling
permissions:
pull-requests: write
if: (success() || failure()) && needs.spelling.outputs.followup && contains(github.event_name, 'pull_request')
steps:
- name: comment
uses: check-spelling/check-spelling@v0.0.21
with:
checkout: true
spell_check_this: check-spelling/spell-check-this@prerelease
task: ${{ needs.spelling.outputs.followup }}

View File

@@ -643,7 +643,8 @@ Global
{DCF55140-EF6A-4736-A403-957E4F7430BB}.Debug|ARM.ActiveCfg = Debug|Win32
{DCF55140-EF6A-4736-A403-957E4F7430BB}.Debug|ARM64.ActiveCfg = Debug|ARM64
{DCF55140-EF6A-4736-A403-957E4F7430BB}.Debug|ARM64.Build.0 = Debug|ARM64
{DCF55140-EF6A-4736-A403-957E4F7430BB}.Debug|DotNet_x64Test.ActiveCfg = Debug|Win32
{DCF55140-EF6A-4736-A403-957E4F7430BB}.Debug|DotNet_x64Test.ActiveCfg = Debug|x64
{DCF55140-EF6A-4736-A403-957E4F7430BB}.Debug|DotNet_x64Test.Build.0 = Debug|x64
{DCF55140-EF6A-4736-A403-957E4F7430BB}.Debug|DotNet_x86Test.ActiveCfg = Debug|Win32
{DCF55140-EF6A-4736-A403-957E4F7430BB}.Debug|x64.ActiveCfg = Debug|x64
{DCF55140-EF6A-4736-A403-957E4F7430BB}.Debug|x64.Build.0 = Debug|x64
@@ -661,7 +662,8 @@ Global
{DCF55140-EF6A-4736-A403-957E4F7430BB}.Release|ARM.ActiveCfg = Release|Win32
{DCF55140-EF6A-4736-A403-957E4F7430BB}.Release|ARM64.ActiveCfg = Release|ARM64
{DCF55140-EF6A-4736-A403-957E4F7430BB}.Release|ARM64.Build.0 = Release|ARM64
{DCF55140-EF6A-4736-A403-957E4F7430BB}.Release|DotNet_x64Test.ActiveCfg = Release|Win32
{DCF55140-EF6A-4736-A403-957E4F7430BB}.Release|DotNet_x64Test.ActiveCfg = Release|x64
{DCF55140-EF6A-4736-A403-957E4F7430BB}.Release|DotNet_x64Test.Build.0 = Release|x64
{DCF55140-EF6A-4736-A403-957E4F7430BB}.Release|DotNet_x86Test.ActiveCfg = Release|Win32
{DCF55140-EF6A-4736-A403-957E4F7430BB}.Release|x64.ActiveCfg = Release|x64
{DCF55140-EF6A-4736-A403-957E4F7430BB}.Release|x64.Build.0 = Release|x64
@@ -2308,7 +2310,8 @@ Global
{48D21369-3D7B-4431-9967-24E81292CF63}.Debug|ARM.ActiveCfg = Debug|Win32
{48D21369-3D7B-4431-9967-24E81292CF63}.Debug|ARM64.ActiveCfg = Debug|ARM64
{48D21369-3D7B-4431-9967-24E81292CF63}.Debug|ARM64.Build.0 = Debug|ARM64
{48D21369-3D7B-4431-9967-24E81292CF63}.Debug|DotNet_x64Test.ActiveCfg = Debug|Win32
{48D21369-3D7B-4431-9967-24E81292CF63}.Debug|DotNet_x64Test.ActiveCfg = Debug|x64
{48D21369-3D7B-4431-9967-24E81292CF63}.Debug|DotNet_x64Test.Build.0 = Debug|x64
{48D21369-3D7B-4431-9967-24E81292CF63}.Debug|DotNet_x86Test.ActiveCfg = Debug|Win32
{48D21369-3D7B-4431-9967-24E81292CF63}.Debug|x64.ActiveCfg = Debug|x64
{48D21369-3D7B-4431-9967-24E81292CF63}.Debug|x64.Build.0 = Debug|x64
@@ -2325,7 +2328,8 @@ Global
{48D21369-3D7B-4431-9967-24E81292CF63}.Release|ARM.ActiveCfg = Release|Win32
{48D21369-3D7B-4431-9967-24E81292CF63}.Release|ARM64.ActiveCfg = Release|ARM64
{48D21369-3D7B-4431-9967-24E81292CF63}.Release|ARM64.Build.0 = Release|ARM64
{48D21369-3D7B-4431-9967-24E81292CF63}.Release|DotNet_x64Test.ActiveCfg = Release|Win32
{48D21369-3D7B-4431-9967-24E81292CF63}.Release|DotNet_x64Test.ActiveCfg = Release|x64
{48D21369-3D7B-4431-9967-24E81292CF63}.Release|DotNet_x64Test.Build.0 = Release|x64
{48D21369-3D7B-4431-9967-24E81292CF63}.Release|DotNet_x86Test.ActiveCfg = Release|Win32
{48D21369-3D7B-4431-9967-24E81292CF63}.Release|x64.ActiveCfg = Release|x64
{48D21369-3D7B-4431-9967-24E81292CF63}.Release|x64.Build.0 = Release|x64
@@ -3313,7 +3317,8 @@ Global
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|ARM.ActiveCfg = Debug|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|ARM64.ActiveCfg = Debug|ARM64
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|ARM64.Build.0 = Debug|ARM64
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|DotNet_x64Test.ActiveCfg = Debug|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|DotNet_x64Test.ActiveCfg = Debug|x64
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|DotNet_x64Test.Build.0 = Debug|x64
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|DotNet_x86Test.ActiveCfg = Debug|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|x64.ActiveCfg = Debug|x64
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|x64.Build.0 = Debug|x64
@@ -3333,7 +3338,8 @@ Global
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|ARM.ActiveCfg = Release|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|ARM64.ActiveCfg = Release|ARM64
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|ARM64.Build.0 = Release|ARM64
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|DotNet_x64Test.ActiveCfg = Release|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|DotNet_x64Test.ActiveCfg = Release|x64
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|DotNet_x64Test.Build.0 = Release|x64
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|DotNet_x86Test.ActiveCfg = Release|Win32
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|x64.ActiveCfg = Release|x64
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|x64.Build.0 = Release|x64

View File

@@ -0,0 +1,117 @@
{
"Version": "1.0.0",
"UseMinimatch": false,
"SignBatches": [
{
"MatchedPath": [
// Namespaced DLLs
"Microsoft.Terminal.*.dll",
"Microsoft.Terminal.*.winmd",
// ConPTY and DefTerm
"OpenConsole.exe",
"OpenConsoleProxy.dll",
// VCRT Forwarders
"*_app.dll",
// Legacy DLLs with old names
"TerminalApp.dll",
"TerminalApp.winmd",
"TerminalConnection.dll",
"TerminalThemeHelpers.dll",
"WindowsTerminalShellExt.dll",
// The rest
"TerminalAzBridge.exe",
"wt.exe",
"WindowsTerminal.exe",
"elevate-shim.exe"
],
"SigningInfo": {
"Operations": [
{
"KeyCode": "CP-230012",
"OperationSetCode": "SigntoolSign",
"Parameters": [
{
"parameterName": "OpusName",
"parameterValue": "Microsoft"
},
{
"parameterName": "OpusInfo",
"parameterValue": "http://www.microsoft.com"
},
{
"parameterName": "FileDigest",
"parameterValue": "/fd \"SHA256\""
},
{
"parameterName": "PageHash",
"parameterValue": "/NPH"
},
{
"parameterName": "TimeStamp",
"parameterValue": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256"
}
],
"ToolName": "sign",
"ToolVersion": "1.0"
},
{
"KeyCode": "CP-230012",
"OperationSetCode": "SigntoolVerify",
"Parameters": [],
"ToolName": "sign",
"ToolVersion": "1.0"
}
]
}
},
{
// THIRD PARTY SOFTWARE
"MatchedPath": [
"cpprest*.dll"
],
"SigningInfo": {
"Operations": [
{
"KeyCode": "CP-231522",
"OperationSetCode": "SigntoolSign",
"Parameters": [
{
"parameterName": "OpusName",
"parameterValue": "Microsoft"
},
{
"parameterName": "OpusInfo",
"parameterValue": "http://www.microsoft.com"
},
{
"parameterName": "FileDigest",
"parameterValue": "/fd \"SHA256\""
},
{
"parameterName": "PageHash",
"parameterValue": "/NPH"
},
{
"parameterName": "TimeStamp",
"parameterValue": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256"
}
],
"ToolName": "sign",
"ToolVersion": "1.0"
},
{
"KeyCode": "CP-231522",
"OperationSetCode": "SigntoolVerify",
"Parameters": [],
"ToolName": "sign",
"ToolVersion": "1.0"
}
]
}
}
]
}

View File

@@ -4,7 +4,7 @@
"collection": "microsoft",
"project": "OS",
"repo": "os.2020",
"name": "official/rs_wdx_dxp_windev",
"name": "official/rs_we_adept_e4d2",
"workitem": "38106206",
"CheckinFiles": [
{
@@ -21,4 +21,4 @@
"sendOnErrorOnly": "False"
}
]
}
}

View File

@@ -9,7 +9,7 @@
<PropertyGroup>
<!-- Optional, defaults to main. Name of the branch which will be used for calculating branch point. -->
<PGOBranch>main</PGOBranch>
<PGOBranch>release-1.16</PGOBranch>
<!-- Mandatory. Name of the NuGet package which will contain PGO databases for consumption by build system. -->
<PGOPackageName>Microsoft.Internal.Windows.Terminal.PGODatabase</PGOPackageName>

View File

@@ -63,6 +63,7 @@ parameters:
- Win11
variables:
MakeAppxPath: 'C:\Program Files (x86)\Windows Kits\10\bin\10.0.22621.0\x86\MakeAppx.exe'
TerminalInternalPackageVersion: "0.0.7"
# If we are building a branch called "release-*", change the NuGet suffix
# to "preview". If we don't do that, XES will set the suffix to "release1"
@@ -270,6 +271,28 @@ jobs:
displayName: 'Generate SBOM manifest'
inputs:
BuildDropPath: '$(System.ArtifactsDirectory)/appx'
- pwsh: |-
$Package = (Get-ChildItem "$(Build.ArtifactStagingDirectory)/appx" -Recurse -Filter "Cascadia*.msix" | Select -First 1)
$PackageFilename = $Package.FullName
Write-Host "##vso[task.setvariable variable=WindowsTerminalPackagePath]${PackageFilename}"
& "$(MakeAppxPath)" unpack /p $PackageFilename /d "$(Build.SourcesDirectory)\UnpackedTerminalPackage"
displayName: Unpack the new Terminal package for signing
- task: EsrpCodeSigning@1
displayName: Submit Terminal's binaries for signing
inputs:
ConnectedServiceName: 9d6d2960-0793-4d59-943e-78dcb434840a
FolderPath: '$(Build.SourcesDirectory)\UnpackedTerminalPackage'
signType: batchSigning
batchSignPolicyFile: '$(Build.SourcesDirectory)\build\config\ESRPSigning_Terminal.json'
- pwsh: |-
$PackageFilename = "$(WindowsTerminalPackagePath)"
Remove-Item "$(Build.SourcesDirectory)\UnpackedTerminalPackage\CodeSignSummary*"
& "$(MakeAppxPath)" pack /h SHA256 /o /p $PackageFilename /d "$(Build.SourcesDirectory)\UnpackedTerminalPackage"
displayName: Re-pack the new Terminal package after signing
- task: PublishBuildArtifacts@1
displayName: Publish Artifact (appx)
inputs:
@@ -708,6 +731,7 @@ jobs:
description: VPack for the Windows Terminal Application
pushPkgName: WindowsTerminal.app
owner: conhost
githubToken: $(GitHubTokenForVpackProvenance)
- task: PublishPipelineArtifact@1
displayName: 'Copy VPack Manifest to Drop'
inputs:

View File

@@ -2,8 +2,8 @@
[Amalgamated](https://github.com/open-source-parsers/jsoncpp/wiki/Amalgamated)
from source commit
[6aba23f](https://github.com/open-source-parsers/jsoncpp/commit/6aba23f4a8628d599a9ef7fa4811c4ff6e4070e2),
release 1.9.3.
[5defb4e](https://github.com/open-source-parsers/jsoncpp/commit/5defb4ed1a4293b8e2bf641e16b156fb9de498cc),
release 1.9.5.
> Generating amalgamated source and header JsonCpp is provided with a script to
> generate a single header and a single source file to ease inclusion into an

View File

@@ -6,7 +6,7 @@
"type": "git",
"git": {
"repositoryUrl": "https://github.com/open-source-parsers/jsoncpp",
"commitHash": "6aba23f4a8628d599a9ef7fa4811c4ff6e4070e2"
"commitHash": "5defb4ed1a4293b8e2bf641e16b156fb9de498cc"
}
}
}

View File

@@ -7,28 +7,28 @@
// //////////////////////////////////////////////////////////////////////
/*
The JsonCpp library's source code, including accompanying documentation,
The JsonCpp library's source code, including accompanying documentation,
tests and demonstration applications, are licensed under the following
conditions...
Baptiste Lepilleur and The JsonCpp Authors explicitly disclaim copyright in all
jurisdictions which recognize such a disclaimer. In such jurisdictions,
Baptiste Lepilleur and The JsonCpp Authors explicitly disclaim copyright in all
jurisdictions which recognize such a disclaimer. In such jurisdictions,
this software is released into the Public Domain.
In jurisdictions which do not recognize Public Domain property (e.g. Germany as of
2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur and
The JsonCpp Authors, and is released under the terms of the MIT License (see below).
In jurisdictions which recognize Public Domain property, the user of this
software may choose to accept it either as 1) Public Domain, 2) under the
conditions of the MIT License (see below), or 3) under the terms of dual
In jurisdictions which recognize Public Domain property, the user of this
software may choose to accept it either as 1) Public Domain, 2) under the
conditions of the MIT License (see below), or 3) under the terms of dual
Public Domain/MIT License conditions described here, as they choose.
The MIT License is about as close to Public Domain as a license can get, and is
described in clear, concise terms at:
http://en.wikipedia.org/wiki/MIT_License
The full text of the MIT License follows:
========================================================================
@@ -94,10 +94,10 @@ license you like.
// 3. /CMakeLists.txt
// IMPORTANT: also update the SOVERSION!!
#define JSONCPP_VERSION_STRING "1.9.3"
#define JSONCPP_VERSION_STRING "1.9.5"
#define JSONCPP_VERSION_MAJOR 1
#define JSONCPP_VERSION_MINOR 9
#define JSONCPP_VERSION_PATCH 3
#define JSONCPP_VERSION_PATCH 5
#define JSONCPP_VERSION_QUALIFIER
#define JSONCPP_VERSION_HEXA \
((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | \
@@ -162,11 +162,10 @@ public:
* Release memory which was allocated for N items at pointer P.
*
* The memory block is filled with zeroes before being released.
* The pointer argument is tagged as "volatile" to prevent the
* compiler optimizing out this critical step.
*/
void deallocate(volatile pointer p, size_type n) {
std::memset(p, 0, n * sizeof(T));
void deallocate(pointer p, size_type n) {
// memset_s is used because memset may be optimized away by the compiler
memset_s(p, n * sizeof(T), 0, n * sizeof(T));
// free using "global operator delete"
::operator delete(p);
}

View File

@@ -6,28 +6,28 @@
// //////////////////////////////////////////////////////////////////////
/*
The JsonCpp library's source code, including accompanying documentation,
The JsonCpp library's source code, including accompanying documentation,
tests and demonstration applications, are licensed under the following
conditions...
Baptiste Lepilleur and The JsonCpp Authors explicitly disclaim copyright in all
jurisdictions which recognize such a disclaimer. In such jurisdictions,
Baptiste Lepilleur and The JsonCpp Authors explicitly disclaim copyright in all
jurisdictions which recognize such a disclaimer. In such jurisdictions,
this software is released into the Public Domain.
In jurisdictions which do not recognize Public Domain property (e.g. Germany as of
2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur and
The JsonCpp Authors, and is released under the terms of the MIT License (see below).
In jurisdictions which recognize Public Domain property, the user of this
software may choose to accept it either as 1) Public Domain, 2) under the
conditions of the MIT License (see below), or 3) under the terms of dual
In jurisdictions which recognize Public Domain property, the user of this
software may choose to accept it either as 1) Public Domain, 2) under the
conditions of the MIT License (see below), or 3) under the terms of dual
Public Domain/MIT License conditions described here, as they choose.
The MIT License is about as close to Public Domain as a license can get, and is
described in clear, concise terms at:
http://en.wikipedia.org/wiki/MIT_License
The full text of the MIT License follows:
========================================================================
@@ -93,10 +93,10 @@ license you like.
// 3. /CMakeLists.txt
// IMPORTANT: also update the SOVERSION!!
#define JSONCPP_VERSION_STRING "1.9.3"
#define JSONCPP_VERSION_STRING "1.9.5"
#define JSONCPP_VERSION_MAJOR 1
#define JSONCPP_VERSION_MINOR 9
#define JSONCPP_VERSION_PATCH 3
#define JSONCPP_VERSION_PATCH 5
#define JSONCPP_VERSION_QUALIFIER
#define JSONCPP_VERSION_HEXA \
((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | \
@@ -161,11 +161,10 @@ public:
* Release memory which was allocated for N items at pointer P.
*
* The memory block is filled with zeroes before being released.
* The pointer argument is tagged as "volatile" to prevent the
* compiler optimizing out this critical step.
*/
void deallocate(volatile pointer p, size_type n) {
std::memset(p, 0, n * sizeof(T));
void deallocate(pointer p, size_type n) {
// memset_s is used because memset may be optimized away by the compiler
memset_s(p, n * sizeof(T), 0, n * sizeof(T));
// free using "global operator delete"
::operator delete(p);
}
@@ -575,7 +574,7 @@ public:
// be used by...
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
#pragma warning(push)
#pragma warning(disable : 4251)
#pragma warning(disable : 4251 4275)
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
#pragma pack(push, 8)
@@ -788,10 +787,10 @@ private:
CZString(ArrayIndex index);
CZString(char const* str, unsigned length, DuplicationPolicy allocate);
CZString(CZString const& other);
CZString(CZString&& other);
CZString(CZString&& other) noexcept;
~CZString();
CZString& operator=(const CZString& other);
CZString& operator=(CZString&& other);
CZString& operator=(CZString&& other) noexcept;
bool operator<(CZString const& other) const;
bool operator==(CZString const& other) const;
@@ -867,14 +866,15 @@ public:
Value(const StaticString& value);
Value(const String& value);
Value(bool value);
Value(std::nullptr_t ptr) = delete;
Value(const Value& other);
Value(Value&& other);
Value(Value&& other) noexcept;
~Value();
/// \note Overwrite existing comments. To preserve comments, use
/// #swapPayload().
Value& operator=(const Value& other);
Value& operator=(Value&& other);
Value& operator=(Value&& other) noexcept;
/// Swap everything.
void swap(Value& other);
@@ -1159,9 +1159,9 @@ private:
public:
Comments() = default;
Comments(const Comments& that);
Comments(Comments&& that);
Comments(Comments&& that) noexcept;
Comments& operator=(const Comments& that);
Comments& operator=(Comments&& that);
Comments& operator=(Comments&& that) noexcept;
bool has(CommentPlacement slot) const;
String get(CommentPlacement slot) const;
void set(CommentPlacement slot, String comment);
@@ -1442,8 +1442,8 @@ public:
* because the returned references/pointers can be used
* to change state of the base class.
*/
reference operator*() { return deref(); }
pointer operator->() { return &deref(); }
reference operator*() const { return const_cast<reference>(deref()); }
pointer operator->() const { return const_cast<pointer>(&deref()); }
};
inline void swap(Value& a, Value& b) { a.swap(b); }
@@ -1506,8 +1506,7 @@ namespace Json {
* \deprecated Use CharReader and CharReaderBuilder.
*/
class JSONCPP_DEPRECATED(
"Use CharReader and CharReaderBuilder instead.") JSON_API Reader {
class JSON_API Reader {
public:
using Char = char;
using Location = const Char*;
@@ -1524,13 +1523,13 @@ public:
};
/** \brief Constructs a Reader allowing all features for parsing.
* \deprecated Use CharReader and CharReaderBuilder.
*/
JSONCPP_DEPRECATED("Use CharReader and CharReaderBuilder instead")
Reader();
/** \brief Constructs a Reader allowing the specified feature set for parsing.
* \deprecated Use CharReader and CharReaderBuilder.
*/
JSONCPP_DEPRECATED("Use CharReader and CharReaderBuilder instead")
Reader(const Features& features);
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
@@ -1797,6 +1796,9 @@ public:
* - `"allowSpecialFloats": false or true`
* - If true, special float values (NaNs and infinities) are allowed and
* their values are lossfree restorable.
* - `"skipBom": false or true`
* - If true, if the input starts with the Unicode byte order mark (BOM),
* it is skipped.
*
* You can examine 'settings_` yourself to see the defaults. You can also
* write and read them just like any JSON Value.
@@ -2000,6 +2002,8 @@ public:
* - Number of precision digits for formatting of real values.
* - "precisionType": "significant"(default) or "decimal"
* - Type of precision for formatting of real values.
* - "emitUTF8": false or true
* - If true, outputs raw UTF8 strings instead of escaping them.
* You can examine 'settings_` yourself
* to see the defaults. You can also write and read them just like any
@@ -2035,7 +2039,7 @@ public:
/** \brief Abstract class for writers.
* \deprecated Use StreamWriter. (And really, this is an implementation detail.)
*/
class JSONCPP_DEPRECATED("Use StreamWriter instead") JSON_API Writer {
class JSON_API Writer {
public:
virtual ~Writer();
@@ -2055,7 +2059,7 @@ public:
#pragma warning(push)
#pragma warning(disable : 4996) // Deriving from deprecated class
#endif
class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API FastWriter
class JSON_API FastWriter
: public Writer {
public:
FastWriter();
@@ -2115,7 +2119,7 @@ private:
#pragma warning(push)
#pragma warning(disable : 4996) // Deriving from deprecated class
#endif
class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API
class JSON_API
StyledWriter : public Writer {
public:
StyledWriter();
@@ -2184,7 +2188,7 @@ private:
#pragma warning(push)
#pragma warning(disable : 4996) // Deriving from deprecated class
#endif
class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API
class JSON_API
StyledStreamWriter {
public:
/**

View File

@@ -6,28 +6,28 @@
// //////////////////////////////////////////////////////////////////////
/*
The JsonCpp library's source code, including accompanying documentation,
The JsonCpp library's source code, including accompanying documentation,
tests and demonstration applications, are licensed under the following
conditions...
Baptiste Lepilleur and The JsonCpp Authors explicitly disclaim copyright in all
jurisdictions which recognize such a disclaimer. In such jurisdictions,
Baptiste Lepilleur and The JsonCpp Authors explicitly disclaim copyright in all
jurisdictions which recognize such a disclaimer. In such jurisdictions,
this software is released into the Public Domain.
In jurisdictions which do not recognize Public Domain property (e.g. Germany as of
2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur and
The JsonCpp Authors, and is released under the terms of the MIT License (see below).
In jurisdictions which recognize Public Domain property, the user of this
software may choose to accept it either as 1) Public Domain, 2) under the
conditions of the MIT License (see below), or 3) under the terms of dual
In jurisdictions which recognize Public Domain property, the user of this
software may choose to accept it either as 1) Public Domain, 2) under the
conditions of the MIT License (see below), or 3) under the terms of dual
Public Domain/MIT License conditions described here, as they choose.
The MIT License is about as close to Public Domain as a license can get, and is
described in clear, concise terms at:
http://en.wikipedia.org/wiki/MIT_License
The full text of the MIT License follows:
========================================================================
@@ -202,14 +202,18 @@ template <typename Iter> void fixNumericLocaleInput(Iter begin, Iter end) {
* Return iterator that would be the new end of the range [begin,end), if we
* were to delete zeros in the end of string, but not the last zero before '.'.
*/
template <typename Iter> Iter fixZerosInTheEnd(Iter begin, Iter end) {
template <typename Iter>
Iter fixZerosInTheEnd(Iter begin, Iter end, unsigned int precision) {
for (; begin != end; --end) {
if (*(end - 1) != '0') {
return end;
}
// Don't delete the last zero before the decimal point.
if (begin != (end - 1) && *(end - 2) == '.') {
return end;
if (begin != (end - 1) && begin != (end - 2) && *(end - 2) == '.') {
if (precision) {
return end;
}
return end - 2;
}
}
return end;
@@ -338,8 +342,7 @@ bool Reader::parse(std::istream& is, Value& root, bool collectComments) {
// Since String is reference-counted, this at least does not
// create an extra copy.
String doc;
std::getline(is, doc, static_cast<char> EOF);
String doc(std::istreambuf_iterator<char>(is), {});
return parse(doc.data(), doc.data() + doc.size(), root, collectComments);
}
@@ -1409,8 +1412,11 @@ bool OurReader::readToken(Token& token) {
if (features_.allowSingleQuotes_) {
token.type_ = tokenString;
ok = readStringSingleQuote();
break;
} // else fall through
} else {
// If we don't allow single quotes, this is a failure case.
ok = false;
}
break;
case '/':
token.type_ = tokenComment;
ok = readComment();
@@ -2152,7 +2158,7 @@ bool CharReaderBuilder::validate(Json::Value* invalid) const {
if (valid_keys.count(key))
continue;
if (invalid)
(*invalid)[std::move(key)] = *si;
(*invalid)[key] = *si;
else
return false;
}
@@ -2667,7 +2673,7 @@ Value::CZString::CZString(const CZString& other) {
storage_.length_ = other.storage_.length_;
}
Value::CZString::CZString(CZString&& other)
Value::CZString::CZString(CZString&& other) noexcept
: cstr_(other.cstr_), index_(other.index_) {
other.cstr_ = nullptr;
}
@@ -2693,7 +2699,7 @@ Value::CZString& Value::CZString::operator=(const CZString& other) {
return *this;
}
Value::CZString& Value::CZString::operator=(CZString&& other) {
Value::CZString& Value::CZString::operator=(CZString&& other) noexcept {
cstr_ = other.cstr_;
index_ = other.index_;
other.cstr_ = nullptr;
@@ -2841,7 +2847,7 @@ Value::Value(const Value& other) {
dupMeta(other);
}
Value::Value(Value&& other) {
Value::Value(Value&& other) noexcept {
initBasic(nullValue);
swap(other);
}
@@ -2856,7 +2862,7 @@ Value& Value::operator=(const Value& other) {
return *this;
}
Value& Value::operator=(Value&& other) {
Value& Value::operator=(Value&& other) noexcept {
other.swap(*this);
return *this;
}
@@ -3320,7 +3326,8 @@ void Value::resize(ArrayIndex newSize) {
if (newSize == 0)
clear();
else if (newSize > oldSize)
this->operator[](newSize - 1);
for (ArrayIndex i = oldSize; i < newSize; ++i)
(*this)[i];
else {
for (ArrayIndex index = newSize; index < oldSize; ++index) {
value_.map_->erase(index);
@@ -3781,14 +3788,15 @@ bool Value::isObject() const { return type() == objectValue; }
Value::Comments::Comments(const Comments& that)
: ptr_{cloneUnique(that.ptr_)} {}
Value::Comments::Comments(Comments&& that) : ptr_{std::move(that.ptr_)} {}
Value::Comments::Comments(Comments&& that) noexcept
: ptr_{std::move(that.ptr_)} {}
Value::Comments& Value::Comments::operator=(const Comments& that) {
ptr_ = cloneUnique(that.ptr_);
return *this;
}
Value::Comments& Value::Comments::operator=(Comments&& that) {
Value::Comments& Value::Comments::operator=(Comments&& that) noexcept {
ptr_ = std::move(that.ptr_);
return *this;
}
@@ -3804,13 +3812,11 @@ String Value::Comments::get(CommentPlacement slot) const {
}
void Value::Comments::set(CommentPlacement slot, String comment) {
if (!ptr_) {
if (slot >= CommentPlacement::numberOfCommentPlacement)
return;
if (!ptr_)
ptr_ = std::unique_ptr<Array>(new Array());
}
// check comments array boundry.
if (slot < CommentPlacement::numberOfCommentPlacement) {
(*ptr_)[slot] = std::move(comment);
}
(*ptr_)[slot] = std::move(comment);
}
void Value::setComment(String comment, CommentPlacement placement) {
@@ -4124,7 +4130,7 @@ Value& Path::make(Value& root) const {
#if !defined(isnan)
// IEEE standard states that NaN values will not compare to themselves
#define isnan(x) (x != x)
#define isnan(x) ((x) != (x))
#endif
#if !defined(__APPLE__)
@@ -4210,16 +4216,18 @@ String valueToString(double value, bool useSpecialFloats,
buffer.erase(fixNumericLocale(buffer.begin(), buffer.end()), buffer.end());
// strip the zero padding from the right
if (precisionType == PrecisionType::decimalPlaces) {
buffer.erase(fixZerosInTheEnd(buffer.begin(), buffer.end()), buffer.end());
}
// try to ensure we preserve the fact that this was given to us as a double on
// input
if (buffer.find('.') == buffer.npos && buffer.find('e') == buffer.npos) {
buffer += ".0";
}
// strip the zero padding from the right
if (precisionType == PrecisionType::decimalPlaces) {
buffer.erase(fixZerosInTheEnd(buffer.begin(), buffer.end(), precision),
buffer.end());
}
return buffer;
}
} // namespace
@@ -4231,11 +4239,11 @@ String valueToString(double value, unsigned int precision,
String valueToString(bool value) { return value ? "true" : "false"; }
static bool isAnyCharRequiredQuoting(char const* s, size_t n) {
static bool doesAnyCharRequireEscaping(char const* s, size_t n) {
assert(s || !n);
return std::any_of(s, s + n, [](unsigned char c) {
return c == '\\' || c == '"' || !std::isprint(c);
return c == '\\' || c == '"' || c < 0x20 || c > 0x7F;
});
}
@@ -4326,12 +4334,12 @@ static void appendHex(String& result, unsigned ch) {
result.append("\\u").append(toHex16Bit(ch));
}
static String valueToQuotedStringN(const char* value, unsigned length,
static String valueToQuotedStringN(const char* value, size_t length,
bool emitUTF8 = false) {
if (value == nullptr)
return "";
if (!isAnyCharRequiredQuoting(value, length))
if (!doesAnyCharRequireEscaping(value, length))
return String("\"") + value + "\"";
// We have to walk value and escape any special characters.
// Appending to String is not efficient, but this should be rare.
@@ -4404,7 +4412,7 @@ static String valueToQuotedStringN(const char* value, unsigned length,
}
String valueToQuotedString(const char* value) {
return valueToQuotedStringN(value, static_cast<unsigned int>(strlen(value)));
return valueToQuotedStringN(value, strlen(value));
}
// Class Writer
@@ -4453,7 +4461,7 @@ void FastWriter::writeValue(const Value& value) {
char const* end;
bool ok = value.getString(&str, &end);
if (ok)
document_ += valueToQuotedStringN(str, static_cast<unsigned>(end - str));
document_ += valueToQuotedStringN(str, static_cast<size_t>(end - str));
break;
}
case booleanValue:
@@ -4476,8 +4484,7 @@ void FastWriter::writeValue(const Value& value) {
const String& name = *it;
if (it != members.begin())
document_ += ',';
document_ += valueToQuotedStringN(name.data(),
static_cast<unsigned>(name.length()));
document_ += valueToQuotedStringN(name.data(), name.length());
document_ += yamlCompatibilityEnabled_ ? ": " : ":";
writeValue(value[name]);
}
@@ -4522,7 +4529,7 @@ void StyledWriter::writeValue(const Value& value) {
char const* end;
bool ok = value.getString(&str, &end);
if (ok)
pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end - str)));
pushValue(valueToQuotedStringN(str, static_cast<size_t>(end - str)));
else
pushValue("");
break;
@@ -4563,7 +4570,7 @@ void StyledWriter::writeValue(const Value& value) {
}
void StyledWriter::writeArrayValue(const Value& value) {
unsigned size = value.size();
size_t size = value.size();
if (size == 0)
pushValue("[]");
else {
@@ -4572,7 +4579,7 @@ void StyledWriter::writeArrayValue(const Value& value) {
writeWithIndent("[");
indent();
bool hasChildValue = !childValues_.empty();
unsigned index = 0;
ArrayIndex index = 0;
for (;;) {
const Value& childValue = value[index];
writeCommentBeforeValue(childValue);
@@ -4595,7 +4602,7 @@ void StyledWriter::writeArrayValue(const Value& value) {
{
assert(childValues_.size() == size);
document_ += "[ ";
for (unsigned index = 0; index < size; ++index) {
for (size_t index = 0; index < size; ++index) {
if (index > 0)
document_ += ", ";
document_ += childValues_[index];
@@ -4740,7 +4747,7 @@ void StyledStreamWriter::writeValue(const Value& value) {
char const* end;
bool ok = value.getString(&str, &end);
if (ok)
pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end - str)));
pushValue(valueToQuotedStringN(str, static_cast<size_t>(end - str)));
else
pushValue("");
break;
@@ -5014,8 +5021,8 @@ void BuiltStyledStreamWriter::writeValue(Value const& value) {
char const* end;
bool ok = value.getString(&str, &end);
if (ok)
pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end - str),
emitUTF8_));
pushValue(
valueToQuotedStringN(str, static_cast<size_t>(end - str), emitUTF8_));
else
pushValue("");
break;
@@ -5038,8 +5045,8 @@ void BuiltStyledStreamWriter::writeValue(Value const& value) {
String const& name = *it;
Value const& childValue = value[name];
writeCommentBeforeValue(childValue);
writeWithIndent(valueToQuotedStringN(
name.data(), static_cast<unsigned>(name.length()), emitUTF8_));
writeWithIndent(
valueToQuotedStringN(name.data(), name.length(), emitUTF8_));
*sout_ << colonSymbol_;
writeValue(childValue);
if (++it == members.end()) {
@@ -5273,7 +5280,7 @@ bool StreamWriterBuilder::validate(Json::Value* invalid) const {
if (valid_keys.count(key))
continue;
if (invalid)
(*invalid)[std::move(key)] = *si;
(*invalid)[key] = *si;
else
return false;
}

View File

@@ -2,7 +2,6 @@
<!-- The packages.config acts as the global version for all of the NuGet packages contained within. -->
<packages>
<!-- Native packages -->
<package id="Microsoft.Toolkit.Win32.UI.XamlApplication" version="6.1.3" targetFramework="native" />
<package id="Microsoft.Internal.PGO-Helpers.Cpp" version="0.2.34" targetFramework="native" />
<package id="Microsoft.Taef" version="10.60.210621002" targetFramework="native" />
<package id="Microsoft.Windows.CppWinRT" version="2.0.210825.3" targetFramework="native" />

View File

@@ -203,7 +203,7 @@
},
"intenseTextStyle": {
"default": "bright",
"description": "Controls how 'intense' text is rendered. Values are \"bold\", \"bright\", \"all\" and \"none\"",
"description": "Controls how 'intense' text is rendered when unfocused. Values are \"bold\", \"bright\", \"all\" and \"none\"",
"enum": [
"none",
"bold",
@@ -244,7 +244,7 @@
"default": 12,
"description": "Size of the font in points.",
"minimum": 1,
"type": "integer"
"type": "number"
},
"weight": {
"default": "normal",
@@ -1546,6 +1546,101 @@
}
]
},
"ShowCloseButton": {
"enum": [
"always",
"hover",
"never"
],
"type": "string"
},
"ThemeColor": {
"description": "A special kind of color for use in themes. Can be an #rrggbb color, #rrggbbaa color, or a special value. 'accent' is evaluated as the user's selected Accent color in the OS, and 'terminalBackground' will be evaluated as the background color of the active terminal pane.",
"oneOf": [
{
"pattern": "^#[A-Fa-f0-9]{3}(?:[A-Fa-f0-9]{3}(?:[A-Fa-f0-9]{2})?)?$",
"type": "string",
"format": "color",
"default": "#000000ff"
},
{
"const": "accent",
"type": "string"
},
{
"const": "terminalBackground",
"type": "string"
},
{
"type": "null"
}
]
},
"TabTheme": {
"additionalProperties": false,
"description": "A set of properties for customizing the appearance of the tabs",
"properties": {
"background": {
"description": "The color of a tab when it is the active tab",
"$ref": "#/$defs/ThemeColor"
},
"unfocusedBackground": {
"description": "The color of a tab when it is not the active tab",
"$ref": "#/$defs/ThemeColor"
},
"showCloseButton": {
"description": "Controls the visibility of the close button on the tab",
"$ref": "#/$defs/ShowCloseButton"
}
}
},
"TabRowTheme": {
"additionalProperties": false,
"description": "A set of properties for customizing the appearance of the tab row",
"properties": {
"background": {
"description": "The color of the tab row when the window is the foreground window.",
"$ref": "#/$defs/ThemeColor"
},
"unfocusedBackground": {
"description": "The color of the tab row when the window is inactive",
"$ref": "#/$defs/ThemeColor"
}
}
},
"WindowTheme": {
"additionalProperties": false,
"description": "A set of properties for customizing the appearance of the window itself",
"properties": {
"applicationTheme": {
"description": "Which UI theme the Terminal should use for controls",
"enum": [ "light", "dark", "system" ],
"type": "string"
}
}
},
"Theme": {
"additionalProperties": false,
"description": "A set of properties for customizing the appearance of the window. This controls things like the titlebar, the tabs, the application theme.",
"properties": {
"name": {
"type": "string",
"description": "The name of the theme. This will be displayed in the settings UI.",
"not": {
"enum": [ "light", "dark", "system" ]
}
},
"tab": {
"$ref": "#/$defs/TabTheme"
},
"tabRow": {
"$ref": "#/$defs/TabRowTheme"
},
"window": {
"$ref": "#/$defs/WindowTheme"
}
}
},
"Keybinding": {
"additionalProperties": false,
"properties": {
@@ -1930,15 +2025,17 @@
"type": "string"
},
"theme": {
"default": "system",
"description": "Sets the theme of the application. The special value \"system\" refers to the active Windows system theme.",
"enum": [
"light",
"dark",
"system"
],
"default": "dark",
"description": "Sets the theme of the application. This value should be the name of one of the themes defined in `themes`. The Terminal also includes the themes `dark`, `light`, and `system`.",
"type": "string"
},
"themes": {
"description": "The list of available themes",
"items": {
"$ref": "#/$defs/Theme"
},
"type": "array"
},
"showTabsInTitlebar": {
"default": true,
"description": "When set to true, the tabs are moved into the titlebar and the titlebar disappears. When set to false, the titlebar sits above the tabs.",
@@ -2252,7 +2349,7 @@
"default": 12,
"description": "[deprecated] Define 'size' within the 'font' object instead.",
"minimum": 1,
"type": "integer",
"type": "number",
"deprecated": true
},
"fontWeight": {
@@ -2283,6 +2380,17 @@
],
"deprecated": true
},
"intenseTextStyle": {
"default": "bright",
"description": "Controls how 'intense' text is rendered. Values are \"bold\", \"bright\", \"all\" and \"none\"",
"enum": [
"none",
"bold",
"bright",
"all"
],
"type": "string"
},
"foreground": {
"$ref": "#/$defs/Color",
"default": "#cccccc",
@@ -2384,7 +2492,10 @@
},
"startingDirectory": {
"description": "The directory the shell starts in when it is loaded.",
"type": "string"
"type": [
"string",
"null"
]
},
"suppressApplicationTitle": {
"description": "When set to true, tabTitle overrides the default title of the tab and any title change messages from the application will be suppressed. When set to false, tabTitle behaves as normal.",

View File

@@ -6,6 +6,7 @@
#include <iostream>
#include <memory>
#include <cassert>
#include <limits>
#ifdef USE_INTERVAL_TREE_NAMESPACE
namespace interval_tree

View File

@@ -8,7 +8,7 @@ That provenance file is automatically read and inventoried by Microsoft systems
## What should be done to update this in the future?
1. Go to ekg/intervaltreerepository on GitHub.
1. Go to the ekg/intervaltree repository on GitHub.
2. Take the file IntervalTree.h wholesale and drop it into the directory here.
3. Don't change anything about it.
4. Validate that the license in the root of the repository didn't change and update it if so. It is sitting in the same directory as this readme.

View File

@@ -6,7 +6,7 @@
"type": "git",
"git": {
"repositoryUrl": "https://github.com/ekg/intervaltree",
"commitHash": "b90527f9e6d51cd36ecbb50429e4524d3a418ea5"
"commitHash": "aa5937755000f1cd007402d03b6f7ce4427c5d21"
}
}
}

View File

@@ -6,7 +6,7 @@
"type": "git",
"git": {
"repositoryUrl": "https://github.com/kimwalisch/libpopcnt",
"commitHash": "043a99fba31121a70bcb2f589faa17f534ae6085"
"commitHash": "c49987e90e56191c399cab881ab87b5daecc9b8e"
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Toolkit.Win32.UI.XamlApplication" version="6.1.3" targetFramework="native" />
<package id="Microsoft.UI.Xaml" version="2.7.1" targetFramework="native" />
<package id="Microsoft.UI.Xaml" version="2.7.3" targetFramework="native" />
<package id="Microsoft.Windows.CppWinRT" version="2.0.210825.3" targetFramework="native" />
</packages>

View File

@@ -2,6 +2,6 @@
<packages>
<package id="Microsoft.Windows.CppWinRT" version="2.0.210825.3" targetFramework="native" />
<package id="Microsoft.Toolkit.Win32.UI.XamlApplication" version="6.1.3" targetFramework="native" />
<package id="Microsoft.UI.Xaml" version="2.7.1" targetFramework="native" />
<package id="Microsoft.UI.Xaml" version="2.7.3" targetFramework="native" />
<package id="Microsoft.VCRTForwarders.140" version="1.0.4" targetFramework="native" />
</packages>

View File

@@ -5,11 +5,6 @@
#include "MidiAudio.hpp"
#include "../terminal/parser/stateMachine.hpp"
#include <dsound.h>
#pragma comment(lib, "dxguid.lib")
#pragma comment(lib, "dsound.lib")
using Microsoft::WRL::ComPtr;
using namespace std::chrono_literals;
@@ -18,66 +13,48 @@ using namespace std::chrono_literals;
constexpr auto WAVE_SIZE = 16u;
constexpr auto WAVE_DATA = std::array<byte, WAVE_SIZE>{ 128, 159, 191, 223, 255, 223, 191, 159, 128, 96, 64, 32, 0, 32, 64, 96 };
MidiAudio::MidiAudio(HWND windowHandle)
void MidiAudio::_initialize(HWND windowHandle) noexcept
{
if (SUCCEEDED(DirectSoundCreate8(nullptr, &_directSound, nullptr)))
_hwnd = windowHandle;
_directSoundModule.reset(LoadLibraryExW(L"dsound.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32));
if (_directSoundModule)
{
if (SUCCEEDED(_directSound->SetCooperativeLevel(windowHandle, DSSCL_NORMAL)))
if (const auto createFunction = GetProcAddressByFunctionDeclaration(_directSoundModule.get(), DirectSoundCreate8))
{
_createBuffers();
if (SUCCEEDED(createFunction(nullptr, &_directSound, nullptr)))
{
if (SUCCEEDED(_directSound->SetCooperativeLevel(windowHandle, DSSCL_NORMAL)))
{
_createBuffers();
}
}
}
}
}
MidiAudio::~MidiAudio() noexcept
void MidiAudio::BeginSkip() noexcept
{
try
{
#pragma warning(suppress : 26447)
// We acquire the lock here so the class isn't destroyed while in use.
// If this throws, we'll catch it, so the C26447 warning is bogus.
const auto lock = std::unique_lock{ _inUseMutex };
}
catch (...)
{
// If the lock fails, we'll just have to live with the consequences.
}
_skip.SetEvent();
}
void MidiAudio::Initialize()
void MidiAudio::EndSkip() noexcept
{
_shutdownFuture = _shutdownPromise.get_future();
_skip.ResetEvent();
}
void MidiAudio::Shutdown()
{
// Once the shutdown promise is set, any note that is playing will stop
// immediately, and the Unlock call will exit the thread ASAP.
_shutdownPromise.set_value();
}
void MidiAudio::Lock()
{
_inUseMutex.lock();
}
void MidiAudio::Unlock()
{
// We need to check the shutdown status before releasing the mutex,
// because after that the class could be destroyed.
const auto shutdownStatus = _shutdownFuture.wait_for(0s);
_inUseMutex.unlock();
// If the wait didn't timeout, that means the shutdown promise was set,
// so we need to exit the thread ASAP by throwing an exception.
if (shutdownStatus != std::future_status::timeout)
{
throw Microsoft::Console::VirtualTerminal::StateMachine::ShutdownException{};
}
}
void MidiAudio::PlayNote(const int noteNumber, const int velocity, const std::chrono::microseconds duration) noexcept
void MidiAudio::PlayNote(HWND windowHandle, const int noteNumber, const int velocity, const std::chrono::milliseconds duration) noexcept
try
{
if (_skip.is_signaled())
{
return;
}
if (_hwnd != windowHandle)
{
_initialize(windowHandle);
}
const auto& buffer = _buffers.at(_activeBufferIndex);
if (velocity && buffer)
{
@@ -100,10 +77,10 @@ try
buffer->SetCurrentPosition((_lastBufferPosition + 12) % WAVE_SIZE);
}
// By waiting on the shutdown future with the duration of the note, we'll
// either be paused for the appropriate amount of time, or we'll break out
// of the wait early if we've been shutdown.
_shutdownFuture.wait_for(duration);
// By waiting on the skip event with a maximum duration of the note, we'll
// either be paused for the appropriate amount of time, or we'll break out early
// because BeginSkip() was called. This happens for Ctrl+C or during shutdown.
_skip.wait(::base::saturated_cast<DWORD>(duration.count()));
if (velocity && buffer)
{

View File

@@ -12,8 +12,6 @@ Abstract:
#pragma once
#include <array>
#include <future>
#include <mutex>
struct IDirectSound8;
struct IDirectSoundBuffer;
@@ -21,26 +19,20 @@ struct IDirectSoundBuffer;
class MidiAudio
{
public:
MidiAudio(HWND windowHandle);
MidiAudio(const MidiAudio&) = delete;
MidiAudio(MidiAudio&&) = delete;
MidiAudio& operator=(const MidiAudio&) = delete;
MidiAudio& operator=(MidiAudio&&) = delete;
~MidiAudio() noexcept;
void Initialize();
void Shutdown();
void Lock();
void Unlock();
void PlayNote(const int noteNumber, const int velocity, const std::chrono::microseconds duration) noexcept;
void BeginSkip() noexcept;
void EndSkip() noexcept;
void PlayNote(HWND windowHandle, const int noteNumber, const int velocity, const std::chrono::milliseconds duration) noexcept;
private:
void _initialize(HWND windowHandle) noexcept;
void _createBuffers() noexcept;
Microsoft::WRL::ComPtr<IDirectSound8> _directSound;
std::array<Microsoft::WRL::ComPtr<IDirectSoundBuffer>, 2> _buffers;
wil::slim_event_manual_reset _skip;
HWND _hwnd = nullptr;
wil::unique_hmodule _directSoundModule;
wil::com_ptr<IDirectSound8> _directSound;
std::array<wil::com_ptr<IDirectSoundBuffer>, 2> _buffers;
size_t _activeBufferIndex = 0;
DWORD _lastBufferPosition = 0;
std::promise<void> _shutdownPromise;
std::future<void> _shutdownFuture;
std::mutex _inUseMutex;
};

View File

@@ -25,7 +25,9 @@ Abstract:
#endif
// Windows Header Files:
#include <windows.h>
#include <Windows.h>
#include <mmeapi.h>
#include <dsound.h>
// clang-format on

View File

@@ -30,7 +30,7 @@ using PointTree = interval_tree::IntervalTree<til::point, size_t>;
// Return Value:
// - constructed object
// Note: may throw exception
TextBuffer::TextBuffer(const til::size screenBufferSize,
TextBuffer::TextBuffer(til::size screenBufferSize,
const TextAttribute defaultAttributes,
const UINT cursorSize,
const bool isActiveBuffer,
@@ -46,6 +46,10 @@ TextBuffer::TextBuffer(const til::size screenBufferSize,
_currentHyperlinkId{ 1 },
_currentPatternId{ 0 }
{
// Guard against resizing the text buffer to 0 columns/rows, which would break being able to insert text.
screenBufferSize.width = std::max(screenBufferSize.width, 1);
screenBufferSize.height = std::max(screenBufferSize.height, 1);
// initialize ROWs
_storage.reserve(gsl::narrow<size_t>(screenBufferSize.Y));
for (til::CoordType i = 0; i < screenBufferSize.Y; ++i)
@@ -896,9 +900,11 @@ void TextBuffer::Reset()
// - newSize - new size of screen.
// Return Value:
// - Success if successful. Invalid parameter if screen buffer size is unexpected. No memory if allocation failed.
[[nodiscard]] NTSTATUS TextBuffer::ResizeTraditional(const til::size newSize) noexcept
[[nodiscard]] NTSTATUS TextBuffer::ResizeTraditional(til::size newSize) noexcept
{
RETURN_HR_IF(E_INVALIDARG, newSize.X < 0 || newSize.Y < 0);
// Guard against resizing the text buffer to 0 columns/rows, which would break being able to insert text.
newSize.width = std::max(newSize.width, 1);
newSize.height = std::max(newSize.height, 1);
try
{
@@ -1032,6 +1038,7 @@ void TextBuffer::_RefreshRowIDs(std::optional<til::CoordType> newRowWidth)
{
std::unordered_map<til::CoordType, til::CoordType> rowMap;
til::CoordType i = 0;
til::CoordType newWidth = newRowWidth.value_or(_storage.at(0).size());
for (auto& it : _storage)
{
// Build a map so we can update Unicode Storage
@@ -1043,12 +1050,13 @@ void TextBuffer::_RefreshRowIDs(std::optional<til::CoordType> newRowWidth)
// Also update the char row parent pointers as they can get shuffled up in the rotates.
it.GetCharRow().UpdateParent(&it);
// Resize the rows in the X dimension if we have a new width
if (newRowWidth.has_value())
{
// Realloc in the X direction
THROW_IF_FAILED(it.Resize(newRowWidth.value()));
}
// Realloc in the X direction
// BODGY: We unpack the optional early and resize here unconditionally
// due to a codegen issue in LKG14. We used to check the optional in
// every iteration of the loop, but that resulted in the optimizer
// emitting a copy of the loop, used when the optional was empty, that
// never exited. Oops.
THROW_IF_FAILED(it.Resize(newWidth));
}
// Give the new mapping to Unicode Storage

View File

@@ -188,8 +188,8 @@
<com:ComInterface>
<com:ProxyStub Id="3171DE52-6EFA-4AEF-8A9F-D02BD67E7A4F" DisplayName="OpenConsoleHandoffProxy" Path="OpenConsoleProxy.dll"/>
<com:Interface Id="E686C757-9A35-4A1C-B3CE-0BCC8B5C69F4" ProxyStubClsid="3171DE52-6EFA-4AEF-8A9F-D02BD67E7A4F"/>
<com:Interface Id="59D55CCE-FC8A-48B4-ACE8-0A9286C6557F" ProxyStubClsid="1833E661-CC81-4DD0-87C6-C2F74BD39EFA"/> <!-- ITerminalHandoff -->
<com:Interface Id="AA6B364F-4A50-4176-9002-0AE755E7B5EF" ProxyStubClsid="1833E661-CC81-4DD0-87C6-C2F74BD39EFA"/> <!-- ITerminalHandoff2 -->
<com:Interface Id="59D55CCE-FC8A-48B4-ACE8-0A9286C6557F" ProxyStubClsid="3171DE52-6EFA-4AEF-8A9F-D02BD67E7A4F"/> <!-- ITerminalHandoff -->
<com:Interface Id="AA6B364F-4A50-4176-9002-0AE755E7B5EF" ProxyStubClsid="3171DE52-6EFA-4AEF-8A9F-D02BD67E7A4F"/> <!-- ITerminalHandoff2 -->
<com:Interface Id="746E6BC0-AB05-4E38-AB14-71E86763141F" ProxyStubClsid="3171DE52-6EFA-4AEF-8A9F-D02BD67E7A4F"/>
</com:ComInterface>
</com:Extension>

View File

@@ -9,7 +9,10 @@
#include <wil/stl.h>
#include <wil/resource.h>
#include <wil/win32_helpers.h>
#include <gsl/gsl_util>
#include <gsl/pointers>
#include <shellapi.h>
#include <appmodel.h>
// BODGY
//
@@ -25,18 +28,68 @@
// process can successfully elevate.
#pragma warning(suppress : 26461) // we can't change the signature of wWinMain
int __stdcall wWinMain(HINSTANCE, HINSTANCE, LPWSTR pCmdLine, int)
int __stdcall wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int)
{
// All of the args passed to us (something like `new-tab -p {guid}`) are in
// pCmdLine
// This will invoke an elevated terminal in two possible ways. See GH#14501
// In both scenarios, it passes the entire cmdline as-is to the new process.
//
// #1 discover and invoke the app using the GetCurrentApplicationUserModelId
// api using shell:AppsFolder\package!appid
// cmd: shell:AppsFolder\WindowsTerminalDev_8wekyb3d8bbwe!App
// params: new-tab -p {guid}
//
// #2 find and execute WindowsTerminal.exe
// cmd: {same path as this binary}\WindowsTerminal.exe
// params: new-tab -p {guid}
// Get the path to WindowsTerminal.exe, which should live next to us.
std::filesystem::path module{ wil::GetModuleFileNameW<std::wstring>(nullptr) };
// Swap elevate-shim.exe for WindowsTerminal.exe
module.replace_filename(L"WindowsTerminal.exe");
// see if we're a store app we can invoke with shell:AppsFolder
std::wstring appUserModelId;
const auto result = wil::AdaptFixedSizeToAllocatedResult<std::wstring, APPLICATION_USER_MODEL_ID_MAX_LENGTH>(
appUserModelId, [&](PWSTR value, size_t valueLength, gsl::not_null<size_t*> valueLengthNeededWithNull) noexcept -> HRESULT {
UINT32 length = gsl::narrow_cast<UINT32>(valueLength);
const LONG rc = GetCurrentApplicationUserModelId(&length, value);
switch (rc)
{
case ERROR_SUCCESS:
*valueLengthNeededWithNull = length;
return S_OK;
case ERROR_INSUFFICIENT_BUFFER:
*valueLengthNeededWithNull = length;
return S_FALSE; // trigger allocation loop
case APPMODEL_ERROR_NO_APPLICATION:
return E_FAIL; // we are not running as a store app
default:
return E_UNEXPECTED;
}
});
LOG_IF_FAILED(result);
std::wstring cmd = {};
if (result == S_OK && appUserModelId.length() > 0)
{
// scenario #1
cmd = L"shell:AppsFolder\\" + appUserModelId;
}
else
{
// scenario #2
// Get the path to WindowsTerminal.exe, which should live next to us.
std::filesystem::path module{
wil::GetModuleFileNameW<std::wstring>(nullptr)
};
// Swap elevate-shim.exe for WindowsTerminal.exe
module.replace_filename(L"WindowsTerminal.exe");
cmd = module;
}
// Go!
// The cmdline argument passed to WinMain is stripping the first argument.
// Using GetCommandLine() instead for lParameters
// disable warnings from SHELLEXECUTEINFOW struct. We can't fix that.
#pragma warning(push)
#pragma warning(disable : 26476) // Macro uses naked union over variant.
@@ -46,8 +99,10 @@ int __stdcall wWinMain(HINSTANCE, HINSTANCE, LPWSTR pCmdLine, int)
seInfo.cbSize = sizeof(seInfo);
seInfo.fMask = SEE_MASK_DEFAULT;
seInfo.lpVerb = L"runas"; // This asks the shell to elevate the process
seInfo.lpFile = module.c_str(); // This is `...\WindowsTerminal.exe`
seInfo.lpParameters = pCmdLine; // This is `new-tab -p {guid}`
seInfo.lpFile = cmd.c_str(); // This is `shell:AppsFolder\...` or `...\WindowsTerminal.exe`
seInfo.lpParameters = GetCommandLine(); // This is `new-tab -p {guid}`
seInfo.nShow = SW_SHOWNORMAL;
LOG_IF_WIN32_BOOL_FALSE(ShellExecuteExW(&seInfo));
return 0;
}

View File

@@ -503,7 +503,7 @@ namespace TerminalAppLocalTests
Log::Comment(NoThrowString().Format(L"Duplicate the first pane"));
result = RunOnUIThread([&page]() {
page->_SplitPane(SplitDirection::Automatic, 0.5f, page->_MakePane(nullptr, true, nullptr));
page->_SplitPane(SplitDirection::Automatic, 0.5f, page->_MakePane(nullptr, page->_GetFocusedTab(), nullptr));
VERIFY_ARE_EQUAL(1u, page->_tabs.Size());
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
@@ -521,7 +521,7 @@ namespace TerminalAppLocalTests
Log::Comment(NoThrowString().Format(L"Duplicate the pane, and don't crash"));
result = RunOnUIThread([&page]() {
page->_SplitPane(SplitDirection::Automatic, 0.5f, page->_MakePane(nullptr, true, nullptr));
page->_SplitPane(SplitDirection::Automatic, 0.5f, page->_MakePane(nullptr, page->_GetFocusedTab(), nullptr));
VERIFY_ARE_EQUAL(1u, page->_tabs.Size());
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
@@ -843,7 +843,7 @@ namespace TerminalAppLocalTests
// | 1 | 2 |
// | | |
// -------------------
page->_SplitPane(SplitDirection::Right, 0.5f, page->_MakePane(nullptr, true, nullptr));
page->_SplitPane(SplitDirection::Right, 0.5f, page->_MakePane(nullptr, page->_GetFocusedTab(), nullptr));
secondId = tab->_activePane->Id().value();
});
Sleep(250);
@@ -861,7 +861,7 @@ namespace TerminalAppLocalTests
// | 3 | |
// | | |
// -------------------
page->_SplitPane(SplitDirection::Down, 0.5f, page->_MakePane(nullptr, true, nullptr));
page->_SplitPane(SplitDirection::Down, 0.5f, page->_MakePane(nullptr, page->_GetFocusedTab(), nullptr));
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
// Split again to make the 3rd tab
thirdId = tab->_activePane->Id().value();
@@ -881,7 +881,7 @@ namespace TerminalAppLocalTests
// | 3 | 4 |
// | | |
// -------------------
page->_SplitPane(SplitDirection::Down, 0.5f, page->_MakePane(nullptr, true, nullptr));
page->_SplitPane(SplitDirection::Down, 0.5f, page->_MakePane(nullptr, page->_GetFocusedTab(), nullptr));
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
fourthId = tab->_activePane->Id().value();
});

View File

@@ -23,7 +23,6 @@
<PropertyGroup Label="NuGet Dependencies">
<!-- TerminalCppWinrt is intentionally not set -->
<TerminalXamlApplicationToolkit>true</TerminalXamlApplicationToolkit>
</PropertyGroup>
<Import Project="$(SolutionDir)\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />

View File

@@ -4,11 +4,7 @@
#include "pch.h"
#include "HwndTerminal.hpp"
#include <windowsx.h>
#include "../../types/TermControlUiaProvider.hpp"
#include <DefaultSettings.h>
#include "../../renderer/base/Renderer.hpp"
#include "../../renderer/dx/DxRenderer.hpp"
#include "../../cascadia/TerminalCore/Terminal.hpp"
#include "../../types/viewport.cpp"
#include "../../types/inc/GlyphWidth.hpp"
@@ -54,6 +50,17 @@ LRESULT CALLBACK HwndTerminal::HwndTerminalWndProc(
LPARAM lParam) noexcept
try
{
if (WM_NCCREATE == uMsg)
{
#pragma warning(suppress : 26490) // Win32 APIs can only store void*, have to use reinterpret_cast
auto cs = reinterpret_cast<CREATESTRUCT*>(lParam);
HwndTerminal* that = static_cast<HwndTerminal*>(cs->lpCreateParams);
that->_hwnd = wil::unique_hwnd(hwnd);
#pragma warning(suppress : 26490) // Win32 APIs can only store void*, have to use reinterpret_cast
SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(that));
return DefWindowProc(hwnd, WM_NCCREATE, wParam, lParam);
}
#pragma warning(suppress : 26490) // Win32 APIs can only store void*, have to use reinterpret_cast
auto terminal = reinterpret_cast<HwndTerminal*>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
@@ -114,11 +121,11 @@ try
}
break;
case WM_RBUTTONDOWN:
if (terminal->_terminal->IsSelectionActive())
if (const auto& termCore{ terminal->_terminal }; termCore && termCore->IsSelectionActive())
{
try
{
const auto bufferData = terminal->_terminal->RetrieveSelectedTextFromBuffer(false);
const auto bufferData = termCore->RetrieveSelectedTextFromBuffer(false);
LOG_IF_FAILED(terminal->_CopyTextToSystemClipboard(bufferData, true));
TerminalClearSelection(terminal);
}
@@ -169,7 +176,7 @@ static bool RegisterTermClass(HINSTANCE hInstance) noexcept
}
HwndTerminal::HwndTerminal(HWND parentHwnd) :
_desiredFont{ L"Consolas", 0, DEFAULT_FONT_WEIGHT, { 0, 14 }, CP_UTF8 },
_desiredFont{ L"Consolas", 0, DEFAULT_FONT_WEIGHT, 14, CP_UTF8 },
_actualFont{ L"Consolas", 0, DEFAULT_FONT_WEIGHT, { 0, 14 }, CP_UTF8, false },
_uiaProvider{ nullptr },
_currentDpi{ USER_DEFAULT_SCREEN_DPI },
@@ -182,7 +189,7 @@ HwndTerminal::HwndTerminal(HWND parentHwnd) :
if (RegisterTermClass(hInstance))
{
_hwnd = wil::unique_hwnd(CreateWindowExW(
CreateWindowExW(
0,
term_window_class,
nullptr,
@@ -197,10 +204,7 @@ HwndTerminal::HwndTerminal(HWND parentHwnd) :
parentHwnd,
nullptr,
hInstance,
nullptr));
#pragma warning(suppress : 26490) // Win32 APIs can only store void*, have to use reinterpret_cast
SetWindowLongPtr(_hwnd.get(), GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
this);
}
}
@@ -277,6 +281,10 @@ CATCH_LOG();
void HwndTerminal::RegisterScrollCallback(std::function<void(int, int, int)> callback)
{
if (!_terminal)
{
return;
}
_terminal->SetScrollPositionChangedCallback(callback);
}
@@ -312,6 +320,10 @@ HWND HwndTerminal::GetHwnd() const noexcept
void HwndTerminal::_UpdateFont(int newDpi)
{
if (!_terminal)
{
return;
}
_currentDpi = newDpi;
auto lock = _terminal->LockForWriting();
@@ -324,14 +336,19 @@ IRawElementProviderSimple* HwndTerminal::_GetUiaProvider() noexcept
{
// If TermControlUiaProvider throws during construction,
// we don't want to try constructing an instance again and again.
// _uiaProviderInitialized helps us prevent this.
if (!_uiaProviderInitialized)
if (!_uiaProvider)
{
try
{
if (!_terminal)
{
return nullptr;
}
auto lock = _terminal->LockForWriting();
LOG_IF_FAILED(::Microsoft::WRL::MakeAndInitialize<::Microsoft::Terminal::TermControlUiaProvider>(&_uiaProvider, this->GetUiaData(), this));
_uiaProviderInitialized = true;
LOG_IF_FAILED(::Microsoft::WRL::MakeAndInitialize<HwndTerminalAutomationPeer>(&_uiaProvider, this->GetUiaData(), this));
_uiaEngine = std::make_unique<::Microsoft::Console::Render::UiaEngine>(_uiaProvider.Get());
LOG_IF_FAILED(_uiaEngine->Enable());
_renderer->AddRenderEngine(_uiaEngine.get());
}
catch (...)
{
@@ -345,6 +362,7 @@ IRawElementProviderSimple* HwndTerminal::_GetUiaProvider() noexcept
HRESULT HwndTerminal::Refresh(const til::size windowSize, _Out_ til::size* dimensions)
{
RETURN_HR_IF_NULL(E_NOT_VALID_STATE, _terminal);
RETURN_HR_IF_NULL(E_INVALIDARG, dimensions);
auto lock = _terminal->LockForWriting();
@@ -360,49 +378,39 @@ HRESULT HwndTerminal::Refresh(const til::size windowSize, _Out_ til::size* dimen
const auto viewInPixels = Viewport::FromDimensions(windowSize);
const auto vp = _renderEngine->GetViewportInCharacters(viewInPixels);
// Guard against resizing the window to 0 columns/rows, which the text buffer classes don't really support.
auto size = vp.Dimensions();
size.width = std::max(size.width, 1);
size.height = std::max(size.height, 1);
// If this function succeeds with S_FALSE, then the terminal didn't
// actually change size. No need to notify the connection of this
// no-op.
// TODO: MSFT:20642295 Resizing the buffer will corrupt it
// I believe we'll need support for CSI 2J, and additionally I think
// we're resetting the viewport to the top
RETURN_IF_FAILED(_terminal->UserResize({ vp.Width(), vp.Height() }));
dimensions->X = vp.Width();
dimensions->Y = vp.Height();
RETURN_IF_FAILED(_terminal->UserResize(size));
dimensions->width = size.width;
dimensions->height = size.height;
return S_OK;
}
void HwndTerminal::SendOutput(std::wstring_view data)
{
if (!_terminal)
{
return;
}
_terminal->Write(data);
}
HRESULT _stdcall CreateTerminal(HWND parentHwnd, _Out_ void** hwnd, _Out_ void** terminal)
{
// In order for UIA to hook up properly there needs to be a "static" window hosting the
// inner win32 control. If the static window is not present then WM_GETOBJECT messages
// will not reach the child control, and the uia element will not be present in the tree.
auto _hostWindow = CreateWindowEx(
0,
L"static",
nullptr,
WS_CHILD |
WS_CLIPCHILDREN |
WS_CLIPSIBLINGS |
WS_VISIBLE,
0,
0,
0,
0,
parentHwnd,
nullptr,
nullptr,
nullptr);
auto _terminal = std::make_unique<HwndTerminal>(_hostWindow);
auto _terminal = std::make_unique<HwndTerminal>(parentHwnd);
RETURN_IF_FAILED(_terminal->Initialize());
*hwnd = _hostWindow;
*hwnd = _terminal->GetHwnd();
*terminal = _terminal.release();
return S_OK;
@@ -487,7 +495,7 @@ HRESULT _stdcall TerminalCalculateResize(_In_ void* terminal, _In_ til::CoordTyp
{
const auto publicTerminal = static_cast<const HwndTerminal*>(terminal);
const auto viewInPixels = Viewport::FromDimensions({ 0, 0 }, { width, height });
const auto viewInPixels = Viewport::FromDimensions({ width, height });
const auto viewInCharacters = publicTerminal->_renderEngine->GetViewportInCharacters(viewInPixels);
dimensions->X = viewInCharacters.Width();
@@ -504,8 +512,10 @@ void _stdcall TerminalDpiChanged(void* terminal, int newDpi)
void _stdcall TerminalUserScroll(void* terminal, int viewTop)
{
const auto publicTerminal = static_cast<const HwndTerminal*>(terminal);
publicTerminal->_terminal->UserScrollViewport(viewTop);
if (const auto publicTerminal = static_cast<const HwndTerminal*>(terminal); publicTerminal && publicTerminal->_terminal)
{
publicTerminal->_terminal->UserScrollViewport(viewTop);
}
}
const unsigned int HwndTerminal::_NumberOfClicks(til::point point, std::chrono::steady_clock::time_point timestamp) noexcept
@@ -527,6 +537,7 @@ const unsigned int HwndTerminal::_NumberOfClicks(til::point point, std::chrono::
HRESULT HwndTerminal::_StartSelection(LPARAM lParam) noexcept
try
{
RETURN_HR_IF_NULL(E_NOT_VALID_STATE, _terminal);
const til::point cursorPosition{
GET_X_LPARAM(lParam),
GET_Y_LPARAM(lParam),
@@ -570,6 +581,7 @@ CATCH_RETURN();
HRESULT HwndTerminal::_MoveSelection(LPARAM lParam) noexcept
try
{
RETURN_HR_IF_NULL(E_NOT_VALID_STATE, _terminal);
const til::point cursorPosition{
GET_X_LPARAM(lParam),
GET_Y_LPARAM(lParam),
@@ -608,6 +620,10 @@ CATCH_RETURN();
void HwndTerminal::_ClearSelection() noexcept
try
{
if (!_terminal)
{
return;
}
auto lock{ _terminal->LockForWriting() };
_terminal->ClearSelection();
_renderer->TriggerSelection();
@@ -622,15 +638,21 @@ void _stdcall TerminalClearSelection(void* terminal)
bool _stdcall TerminalIsSelectionActive(void* terminal)
{
const auto publicTerminal = static_cast<const HwndTerminal*>(terminal);
const auto selectionActive = publicTerminal->_terminal->IsSelectionActive();
return selectionActive;
if (const auto publicTerminal = static_cast<const HwndTerminal*>(terminal); publicTerminal && publicTerminal->_terminal)
{
return publicTerminal->_terminal->IsSelectionActive();
}
return false;
}
// Returns the selected text in the terminal.
const wchar_t* _stdcall TerminalGetSelection(void* terminal)
{
auto publicTerminal = static_cast<HwndTerminal*>(terminal);
if (!publicTerminal || !publicTerminal->_terminal)
{
return nullptr;
}
const auto bufferData = publicTerminal->_terminal->RetrieveSelectedTextFromBuffer(false);
publicTerminal->_ClearSelection();
@@ -682,12 +704,17 @@ bool HwndTerminal::_CanSendVTMouseInput() const noexcept
{
// Only allow the transit of mouse events if shift isn't pressed.
const auto shiftPressed = GetKeyState(VK_SHIFT) < 0;
return !shiftPressed && _focused && _terminal->IsTrackingMouseInput();
return !shiftPressed && _focused && _terminal && _terminal->IsTrackingMouseInput();
}
bool HwndTerminal::_SendMouseEvent(UINT uMsg, WPARAM wParam, LPARAM lParam) noexcept
try
{
if (!_terminal)
{
return false;
}
til::point cursorPosition{
GET_X_LPARAM(lParam),
GET_Y_LPARAM(lParam),
@@ -720,11 +747,20 @@ catch (...)
void HwndTerminal::_SendKeyEvent(WORD vkey, WORD scanCode, WORD flags, bool keyDown) noexcept
try
{
if (!_terminal)
{
return;
}
auto modifiers = getControlKeyState();
if (WI_IsFlagSet(flags, ENHANCED_KEY))
{
modifiers |= ControlKeyStates::EnhancedKey;
}
if (vkey && keyDown && _uiaProvider)
{
_uiaProvider->RecordKeyEvent(vkey);
}
_terminal->SendKeyEvent(vkey, scanCode, modifiers, keyDown);
}
CATCH_LOG();
@@ -732,7 +768,11 @@ CATCH_LOG();
void HwndTerminal::_SendCharEvent(wchar_t ch, WORD scanCode, WORD flags) noexcept
try
{
if (_terminal->IsSelectionActive())
if (!_terminal)
{
return;
}
else if (_terminal->IsSelectionActive())
{
_ClearSelection();
if (ch == UNICODE_ESC)
@@ -780,6 +820,10 @@ void _stdcall DestroyTerminal(void* terminal)
void _stdcall TerminalSetTheme(void* terminal, TerminalTheme theme, LPCWSTR fontFamily, til::CoordType fontSize, int newDpi)
{
const auto publicTerminal = static_cast<HwndTerminal*>(terminal);
if (!publicTerminal || !publicTerminal->_terminal)
{
return;
}
{
auto lock = publicTerminal->_terminal->LockForWriting();
@@ -799,7 +843,7 @@ void _stdcall TerminalSetTheme(void* terminal, TerminalTheme theme, LPCWSTR font
publicTerminal->_terminal->SetCursorStyle(static_cast<DispatchTypes::CursorStyle>(theme.CursorStyle));
publicTerminal->_desiredFont = { fontFamily, 0, DEFAULT_FONT_WEIGHT, { 0, fontSize }, CP_UTF8 };
publicTerminal->_desiredFont = { fontFamily, 0, DEFAULT_FONT_WEIGHT, static_cast<float>(fontSize), CP_UTF8 };
publicTerminal->_UpdateFont(newDpi);
// When the font changes the terminal dimensions need to be recalculated since the available row and column
@@ -815,7 +859,7 @@ void _stdcall TerminalSetTheme(void* terminal, TerminalTheme theme, LPCWSTR font
void _stdcall TerminalBlinkCursor(void* terminal)
{
const auto publicTerminal = static_cast<const HwndTerminal*>(terminal);
if (!publicTerminal->_terminal->IsCursorBlinkingAllowed() && publicTerminal->_terminal->IsCursorVisible())
if (!publicTerminal || !publicTerminal->_terminal || (!publicTerminal->_terminal->IsCursorBlinkingAllowed() && publicTerminal->_terminal->IsCursorVisible()))
{
return;
}
@@ -826,6 +870,10 @@ void _stdcall TerminalBlinkCursor(void* terminal)
void _stdcall TerminalSetCursorVisible(void* terminal, const bool visible)
{
const auto publicTerminal = static_cast<const HwndTerminal*>(terminal);
if (!publicTerminal || !publicTerminal->_terminal)
{
return;
}
publicTerminal->_terminal->SetCursorOn(visible);
}
@@ -833,12 +881,20 @@ void __stdcall TerminalSetFocus(void* terminal)
{
auto publicTerminal = static_cast<HwndTerminal*>(terminal);
publicTerminal->_focused = true;
if (auto uiaEngine = publicTerminal->_uiaEngine.get())
{
LOG_IF_FAILED(uiaEngine->Enable());
}
}
void __stdcall TerminalKillFocus(void* terminal)
{
auto publicTerminal = static_cast<HwndTerminal*>(terminal);
publicTerminal->_focused = false;
if (auto uiaEngine = publicTerminal->_uiaEngine.get())
{
LOG_IF_FAILED(uiaEngine->Disable());
}
}
// Routine Description:
@@ -849,6 +905,7 @@ void __stdcall TerminalKillFocus(void* terminal)
HRESULT HwndTerminal::_CopyTextToSystemClipboard(const TextBuffer::TextAndColor& rows, const bool fAlsoCopyFormatting)
try
{
RETURN_HR_IF_NULL(E_NOT_VALID_STATE, _terminal);
std::wstring finalString;
// Concatenate strings into one giant string to put onto the clipboard.
@@ -1005,6 +1062,10 @@ double HwndTerminal::GetScaleFactor() const noexcept
void HwndTerminal::ChangeViewport(const til::inclusive_rect& NewWindow)
{
if (!_terminal)
{
return;
}
_terminal->UserScrollViewport(NewWindow.Top);
}

View File

@@ -5,10 +5,10 @@
#include "../../renderer/base/Renderer.hpp"
#include "../../renderer/dx/DxRenderer.hpp"
#include "../../renderer/uia/UiaRenderer.hpp"
#include "../../cascadia/TerminalCore/Terminal.hpp"
#include <UIAutomationCore.h>
#include "../../types/IControlAccessibilityInfo.h"
#include "../../types/TermControlUiaProvider.hpp"
#include "HwndTerminalAutomationPeer.hpp"
using namespace Microsoft::Console::VirtualTerminal;
@@ -74,15 +74,15 @@ private:
FontInfo _actualFont;
int _currentDpi;
std::function<void(wchar_t*)> _pfnWriteCallback;
::Microsoft::WRL::ComPtr<::Microsoft::Terminal::TermControlUiaProvider> _uiaProvider;
::Microsoft::WRL::ComPtr<HwndTerminalAutomationPeer> _uiaProvider;
std::unique_ptr<::Microsoft::Terminal::Core::Terminal> _terminal;
std::unique_ptr<::Microsoft::Console::Render::Renderer> _renderer;
std::unique_ptr<::Microsoft::Console::Render::DxEngine> _renderEngine;
std::unique_ptr<::Microsoft::Console::Render::UiaEngine> _uiaEngine;
bool _focused{ false };
bool _uiaProviderInitialized{ false };
std::chrono::milliseconds _multiClickTime;
unsigned int _multiClickCounter{};

View File

@@ -0,0 +1,159 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "HwndTerminalAutomationPeer.hpp"
#include "../../types/UiaTracing.h"
#include <UIAutomationCoreApi.h>
#pragma warning(suppress : 4471) // We don't control UIAutomationClient
#include <UIAutomationClient.h>
using namespace Microsoft::Console::Types;
static constexpr wchar_t UNICODE_NEWLINE{ L'\n' };
// Method Description:
// - creates a copy of the provided text with all of the control characters removed
// Arguments:
// - text: the string we're sanitizing
// Return Value:
// - a copy of "sanitized" with all of the control characters removed
static std::wstring Sanitize(std::wstring_view text)
{
std::wstring sanitized{ text };
sanitized.erase(std::remove_if(sanitized.begin(), sanitized.end(), [](wchar_t c) {
return (c < UNICODE_SPACE && c != UNICODE_NEWLINE) || c == 0x7F /*DEL*/;
}),
sanitized.end());
return sanitized;
}
// Method Description:
// - verifies if a given string has text that would be read by a screen reader.
// - a string of control characters, for example, would not be read.
// Arguments:
// - text: the string we're validating
// Return Value:
// - true, if the text is readable. false, otherwise.
static constexpr bool IsReadable(std::wstring_view text)
{
for (const auto c : text)
{
if (c > UNICODE_SPACE)
{
return true;
}
}
return false;
}
void HwndTerminalAutomationPeer::RecordKeyEvent(const WORD vkey)
{
if (const auto charCode{ MapVirtualKey(vkey, MAPVK_VK_TO_CHAR) })
{
if (const auto keyEventChar{ gsl::narrow_cast<wchar_t>(charCode) }; IsReadable({ &keyEventChar, 1 }))
{
_keyEvents.emplace_back(keyEventChar);
}
}
}
// Implementation of IRawElementProviderSimple::get_PropertyValue.
// Gets custom properties.
IFACEMETHODIMP HwndTerminalAutomationPeer::GetPropertyValue(_In_ PROPERTYID propertyId,
_Out_ VARIANT* pVariant) noexcept
{
pVariant->vt = VT_EMPTY;
// Returning the default will leave the property as the default
// so we only really need to touch it for the properties we want to implement
if (propertyId == UIA_ClassNamePropertyId)
{
// IMPORTANT: Do NOT change the name. Screen readers like may be dependent on this being "WpfTermControl".
pVariant->bstrVal = SysAllocString(L"WPFTermControl");
if (pVariant->bstrVal != nullptr)
{
pVariant->vt = VT_BSTR;
}
}
else
{
// fall back to shared implementation
return TermControlUiaProvider::GetPropertyValue(propertyId, pVariant);
}
return S_OK;
}
// Method Description:
// - Signals the ui automation client that the terminal's selection has changed and should be updated
// Arguments:
// - <none>
// Return Value:
// - <none>
void HwndTerminalAutomationPeer::SignalSelectionChanged()
{
UiaTracing::Signal::SelectionChanged();
LOG_IF_FAILED(UiaRaiseAutomationEvent(this, UIA_Text_TextSelectionChangedEventId));
}
// Method Description:
// - Signals the ui automation client that the terminal's output has changed and should be updated
// Arguments:
// - <none>
// Return Value:
// - <none>
void HwndTerminalAutomationPeer::SignalTextChanged()
{
UiaTracing::Signal::TextChanged();
LOG_IF_FAILED(UiaRaiseAutomationEvent(this, UIA_Text_TextChangedEventId));
}
// Method Description:
// - Signals the ui automation client that the cursor's state has changed and should be updated
// Arguments:
// - <none>
// Return Value:
// - <none>
void HwndTerminalAutomationPeer::SignalCursorChanged()
{
UiaTracing::Signal::CursorChanged();
LOG_IF_FAILED(UiaRaiseAutomationEvent(this, UIA_Text_TextSelectionChangedEventId));
}
void HwndTerminalAutomationPeer::NotifyNewOutput(std::wstring_view newOutput)
{
// Try to suppress any events (or event data)
// that is just the keypress the user made
auto sanitized{ Sanitize(newOutput) };
while (!_keyEvents.empty() && IsReadable(sanitized))
{
if (til::toupper_ascii(sanitized.front()) == _keyEvents.front())
{
// the key event's character (i.e. the "A" key) matches
// the output character (i.e. "a" or "A" text).
// We can assume that the output character resulted from
// the pressed key, so we can ignore it.
sanitized = sanitized.substr(1);
_keyEvents.pop_front();
}
else
{
// The output doesn't match,
// so clear the input stack and
// move on to fire the event.
_keyEvents.clear();
break;
}
}
// Suppress event if the remaining text is not readable
if (!IsReadable(sanitized))
{
return;
}
const auto sanitizedBstr = wil::make_bstr_nothrow(sanitized.c_str());
static auto activityId = wil::make_bstr_nothrow(L"TerminalTextOutput");
LOG_IF_FAILED(UiaRaiseNotificationEvent(this, NotificationKind_ActionCompleted, NotificationProcessing_All, sanitizedBstr.get(), activityId.get()));
}

View File

@@ -0,0 +1,42 @@
/*++
Copyright (c) Microsoft Corporation
Licensed under the MIT license.
Module Name:
- HwndTerminalAutomationPeer.hpp
Abstract:
- This module provides UI Automation access to the HwndTerminal
to support both automation tests and accessibility (screen
reading) applications. This mainly interacts with TermControlUiaProvider
to allow for shared code with Windows Terminal accessibility providers.
Author(s):
- Carlos Zamora (CaZamor) 2022
--*/
#pragma once
#include "../types/TermControlUiaProvider.hpp"
#include "../types/IUiaEventDispatcher.h"
#include "../types/IControlAccessibilityInfo.h"
class HwndTerminalAutomationPeer :
public ::Microsoft::Console::Types::IUiaEventDispatcher,
public ::Microsoft::Terminal::TermControlUiaProvider
{
public:
void RecordKeyEvent(const WORD vkey);
IFACEMETHODIMP GetPropertyValue(_In_ PROPERTYID idProp,
_Out_ VARIANT* pVariant) noexcept override;
#pragma region IUiaEventDispatcher
void SignalSelectionChanged() override;
void SignalTextChanged() override;
void SignalCursorChanged() override;
void NotifyNewOutput(std::wstring_view newOutput) override;
#pragma endregion
private:
std::deque<wchar_t> _keyEvents;
};

View File

@@ -15,9 +15,11 @@
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="HwndTerminal.cpp" />
<ClCompile Include="HwndTerminalAutomationPeer.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="HwndTerminal.hpp" />
<ClInclude Include="HwndTerminalAutomationPeer.hpp" />
<ClInclude Include="pch.h" />
</ItemGroup>
<ItemGroup>
@@ -39,6 +41,9 @@
<ProjectReference Include="$(SolutionDir)src\renderer\dx\lib\dx.vcxproj">
<Project>{48d21369-3d7b-4431-9967-24e81292cf62}</Project>
</ProjectReference>
<ProjectReference Include="..\..\renderer\uia\lib\uia.vcxproj">
<Project>{48d21369-3d7b-4431-9967-24e81292cf63}</Project>
</ProjectReference>
</ItemGroup>
<ItemDefinitionGroup>
<ClCompile>
@@ -55,4 +60,4 @@
<AdditionalDependencies>Uiautomationcore.lib;onecoreuap.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
</Project>
</Project>

View File

@@ -24,6 +24,9 @@
<ClCompile Include="HwndTerminal.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="HwndTerminalAutomationPeer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="pch.h">
@@ -32,5 +35,8 @@
<ClInclude Include="HwndTerminal.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="HwndTerminalAutomationPeer.hpp">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@@ -9,3 +9,4 @@
#endif
#include <LibraryIncludes.h>
#include <UIAutomationCore.h>

View File

@@ -25,37 +25,25 @@ static constexpr std::wstring_view VerbName{ L"WindowsTerminalOpenHere" };
// failure from an earlier HRESULT.
HRESULT OpenTerminalHere::Invoke(IShellItemArray* psiItemArray,
IBindCtx* /*pBindContext*/)
try
{
wil::com_ptr_nothrow<IShellItem> psi;
RETURN_IF_FAILED(GetBestLocationFromSelectionOrSite(psiItemArray, psi.put()));
if (!psi)
{
return S_FALSE;
}
wil::unique_cotaskmem_string pszName;
if (psiItemArray == nullptr)
{
// get the current path from explorer.exe
const auto path = this->_GetPathFromExplorer();
// no go, unable to get a reasonable path
if (path.empty())
{
return S_FALSE;
}
pszName = wil::make_cotaskmem_string(path.c_str(), path.length());
}
else
{
DWORD count;
psiItemArray->GetCount(&count);
winrt::com_ptr<IShellItem> psi;
RETURN_IF_FAILED(psiItemArray->GetItemAt(0, psi.put()));
RETURN_IF_FAILED(psi->GetDisplayName(SIGDN_FILESYSPATH, &pszName));
}
RETURN_IF_FAILED(psi->GetDisplayName(SIGDN_FILESYSPATH, &pszName));
{
wil::unique_process_information _piClient;
STARTUPINFOEX siEx{ 0 };
siEx.StartupInfo.cb = sizeof(STARTUPINFOEX);
auto cmdline{ wil::str_printf<std::wstring>(LR"-("%s" -d %s)-", GetWtExePath().c_str(), QuoteAndEscapeCommandlineArg(pszName.get()).c_str()) };
std::wstring cmdline;
RETURN_IF_FAILED(wil::str_printf_nothrow(cmdline, LR"-("%s" -d %s)-", GetWtExePath().c_str(), QuoteAndEscapeCommandlineArg(pszName.get()).c_str()));
RETURN_IF_WIN32_BOOL_FALSE(CreateProcessW(
nullptr, // lpApplicationName
cmdline.data(),
@@ -72,6 +60,7 @@ HRESULT OpenTerminalHere::Invoke(IShellItemArray* psiItemArray,
return S_OK;
}
CATCH_RETURN()
HRESULT OpenTerminalHere::GetToolTip(IShellItemArray* /*psiItemArray*/,
LPWSTR* ppszInfoTip)
@@ -109,21 +98,14 @@ HRESULT OpenTerminalHere::GetState(IShellItemArray* psiItemArray,
// We however don't need to bother with any of that.
// If no item was selected when the context menu was opened and Explorer
// is not at a valid path (e.g. This PC or Quick Access), we should hide
// is not at a valid location (e.g. This PC or Quick Access), we should hide
// the verb from the context menu.
if (psiItemArray == nullptr)
{
const auto path = this->_GetPathFromExplorer();
*pCmdState = path.empty() ? ECS_HIDDEN : ECS_ENABLED;
}
else
{
winrt::com_ptr<IShellItem> psi;
psiItemArray->GetItemAt(0, psi.put());
SFGAOF attributes;
const bool isFileSystemItem = (psi->GetAttributes(SFGAO_FILESYSTEM, &attributes) == S_OK);
*pCmdState = isFileSystemItem ? ECS_ENABLED : ECS_HIDDEN;
}
wil::com_ptr_nothrow<IShellItem> psi;
RETURN_IF_FAILED(GetBestLocationFromSelectionOrSite(psiItemArray, psi.put()));
SFGAOF attributes;
const bool isFileSystemItem = psi && (psi->GetAttributes(SFGAO_FILESYSTEM, &attributes) == S_OK);
*pCmdState = isFileSystemItem ? ECS_ENABLED : ECS_HIDDEN;
return S_OK;
}
@@ -160,102 +142,54 @@ HRESULT OpenTerminalHere::EnumSubCommands(IEnumExplorerCommand** ppEnum)
return E_NOTIMPL;
}
std::wstring OpenTerminalHere::_GetPathFromExplorer() const
IFACEMETHODIMP OpenTerminalHere::SetSite(IUnknown* site) noexcept
{
using namespace std;
using namespace winrt;
wstring path;
HRESULT hr = NOERROR;
auto hwnd = ::GetForegroundWindow();
if (hwnd == nullptr)
{
return path;
}
TCHAR szName[MAX_PATH] = { 0 };
::GetClassName(hwnd, szName, MAX_PATH);
if (0 == StrCmp(szName, L"WorkerW") ||
0 == StrCmp(szName, L"Progman"))
{
//special folder: desktop
hr = ::SHGetFolderPath(NULL, CSIDL_DESKTOP, NULL, SHGFP_TYPE_CURRENT, szName);
if (FAILED(hr))
{
return path;
}
path = szName;
return path;
}
if (0 != StrCmp(szName, L"CabinetWClass"))
{
return path;
}
com_ptr<IShellWindows> shell;
try
{
shell = create_instance<IShellWindows>(CLSID_ShellWindows, CLSCTX_ALL);
}
catch (...)
{
//look like try_create_instance is not available no more
}
if (shell == nullptr)
{
return path;
}
com_ptr<IDispatch> disp;
wil::unique_variant variant;
variant.vt = VT_I4;
com_ptr<IWebBrowserApp> browser;
// look for correct explorer window
for (variant.intVal = 0;
shell->Item(variant, disp.put()) == S_OK;
variant.intVal++)
{
com_ptr<IWebBrowserApp> tmp;
if (FAILED(disp->QueryInterface(tmp.put())))
{
disp = nullptr; // get rid of DEBUG non-nullptr warning
continue;
}
HWND tmpHWND = NULL;
hr = tmp->get_HWND(reinterpret_cast<SHANDLE_PTR*>(&tmpHWND));
if (hwnd == tmpHWND)
{
browser = tmp;
disp = nullptr; // get rid of DEBUG non-nullptr warning
break; //found
}
disp = nullptr; // get rid of DEBUG non-nullptr warning
}
if (browser != nullptr)
{
wil::unique_bstr url;
hr = browser->get_LocationURL(&url);
if (FAILED(hr))
{
return path;
}
wstring sUrl(url.get(), SysStringLen(url.get()));
DWORD size = MAX_PATH;
hr = ::PathCreateFromUrl(sUrl.c_str(), szName, &size, NULL);
if (SUCCEEDED(hr))
{
path = szName;
}
}
return path;
site_ = site;
return S_OK;
}
IFACEMETHODIMP OpenTerminalHere::GetSite(REFIID riid, void** site) noexcept
{
RETURN_IF_FAILED(site_.query_to(riid, site));
return S_OK;
}
HRESULT OpenTerminalHere::GetLocationFromSite(IShellItem** location) const noexcept
{
wil::assign_null_to_opt_param(location);
if (!site_)
{
return S_FALSE;
}
wil::com_ptr_nothrow<IServiceProvider> serviceProvider;
RETURN_IF_FAILED(site_.query_to(serviceProvider.put()));
wil::com_ptr_nothrow<IFolderView> folderView;
RETURN_IF_FAILED(serviceProvider->QueryService(SID_SFolderView, IID_PPV_ARGS(folderView.put())));
RETURN_IF_FAILED(folderView->GetFolder(IID_PPV_ARGS(location)));
return S_OK;
}
HRESULT OpenTerminalHere::GetBestLocationFromSelectionOrSite(IShellItemArray* psiArray, IShellItem** location) const noexcept
{
wil::com_ptr_nothrow<IShellItem> psi;
if (psiArray)
{
DWORD count{};
RETURN_IF_FAILED(psiArray->GetCount(&count));
if (count) // Sometimes we get an array with a count of 0. Fall back to the site chain.
{
RETURN_IF_FAILED(psiArray->GetItemAt(0, psi.put()));
}
}
if (!psi)
{
RETURN_IF_FAILED(GetLocationFromSite(psi.put()));
}
RETURN_HR_IF(S_FALSE, !psi);
RETURN_IF_FAILED(psi.copy_to(location));
return S_OK;
}

View File

@@ -22,8 +22,6 @@ Author(s):
--*/
#pragma once
#include <conattrs.hpp>
using namespace Microsoft::WRL;
struct
@@ -34,7 +32,7 @@ struct
#else // DEV
__declspec(uuid("52065414-e077-47ec-a3ac-1cc5455e1b54"))
#endif
OpenTerminalHere : public RuntimeClass<RuntimeClassFlags<ClassicCom | InhibitFtmBase>, IExplorerCommand>
OpenTerminalHere : public RuntimeClass<RuntimeClassFlags<ClassicCom | InhibitFtmBase>, IExplorerCommand, IObjectWithSite>
{
#pragma region IExplorerCommand
STDMETHODIMP Invoke(IShellItemArray* psiItemArray,
@@ -52,9 +50,16 @@ struct
STDMETHODIMP GetCanonicalName(GUID* pguidCommandName);
STDMETHODIMP EnumSubCommands(IEnumExplorerCommand** ppEnum);
#pragma endregion
#pragma region IObjectWithSite
IFACEMETHODIMP SetSite(IUnknown* site) noexcept;
IFACEMETHODIMP GetSite(REFIID riid, void** site) noexcept;
#pragma endregion
private:
std::wstring _GetPathFromExplorer() const;
HRESULT GetLocationFromSite(IShellItem** location) const noexcept;
HRESULT GetBestLocationFromSelectionOrSite(IShellItemArray* psiArray, IShellItem** location) const noexcept;
wil::com_ptr_nothrow<IUnknown> site_;
};
CoCreatableClass(OpenTerminalHere);

View File

@@ -12,19 +12,12 @@ using namespace winrt::Windows::UI::Xaml;
using namespace winrt::Windows::UI::Xaml::Controls;
using namespace winrt::Windows::UI::Xaml::Navigation;
namespace xaml = ::winrt::Windows::UI::Xaml;
namespace winrt::TerminalApp::implementation
{
App::App()
{
// This is the same trick that Initialize() is about to use to figure out whether we're coming
// from a UWP context or from a Win32 context
// See https://github.com/windows-toolkit/Microsoft.Toolkit.Win32/blob/52611c57d89554f357f281d0c79036426a7d9257/Microsoft.Toolkit.Win32.UI.XamlApplication/XamlApplication.cpp#L42
const auto dispatcherQueue = ::winrt::Windows::System::DispatcherQueue::GetForCurrentThread();
if (dispatcherQueue)
{
_isUwp = true;
}
Initialize();
// Disable XAML's automatic backplating of text when in High Contrast
@@ -33,12 +26,50 @@ namespace winrt::TerminalApp::implementation
HighContrastAdjustment(::winrt::Windows::UI::Xaml::ApplicationHighContrastAdjustment::None);
}
void App::Initialize()
{
const auto dispatcherQueue = winrt::Windows::System::DispatcherQueue::GetForCurrentThread();
if (!dispatcherQueue)
{
_windowsXamlManager = xaml::Hosting::WindowsXamlManager::InitializeForCurrentThread();
}
else
{
_isUwp = true;
}
}
AppLogic App::Logic()
{
static AppLogic logic;
return logic;
}
void App::Close()
{
if (_bIsClosed)
{
return;
}
_bIsClosed = true;
if (_windowsXamlManager)
{
_windowsXamlManager.Close();
}
_windowsXamlManager = nullptr;
Exit();
{
MSG msg = {};
while (PeekMessageW(&msg, nullptr, 0, 0, PM_REMOVE))
{
::DispatchMessageW(&msg);
}
}
}
/// <summary>
/// Invoked when the application is launched normally by the end user. Other entry points
/// will be used such as when the application is launched to open a specific file.

View File

@@ -5,6 +5,7 @@
#include "App.g.h"
#include "App.base.h"
#include <winrt/Windows.UI.Xaml.Hosting.h>
namespace winrt::TerminalApp::implementation
{
@@ -13,11 +14,22 @@ namespace winrt::TerminalApp::implementation
public:
App();
void OnLaunched(const Windows::ApplicationModel::Activation::LaunchActivatedEventArgs&);
void Initialize();
TerminalApp::AppLogic Logic();
void Close();
bool IsDisposed() const
{
return _bIsClosed;
}
private:
bool _isUwp = false;
winrt::Windows::UI::Xaml::Hosting::WindowsXamlManager _windowsXamlManager = nullptr;
winrt::Windows::Foundation::Collections::IVector<winrt::Windows::UI::Xaml::Markup::IXamlMetadataProvider> _providers = winrt::single_threaded_vector<Windows::UI::Xaml::Markup::IXamlMetadataProvider>();
bool _bIsClosed = false;
};
}

View File

@@ -7,10 +7,12 @@ namespace TerminalApp
{
// ADD ARBITRARY APP LOGIC TO AppLogic.idl, NOT HERE.
// This is for XAML platform setup only.
[default_interface] runtimeclass App : Microsoft.Toolkit.Win32.UI.XamlHost.XamlApplication
[default_interface] runtimeclass App : Windows.UI.Xaml.Application, Windows.Foundation.IClosable
{
App();
AppLogic Logic { get; };
Boolean IsDisposed { get; };
}
}

View File

@@ -2,20 +2,19 @@
Copyright (c) Microsoft Corporation. All rights reserved. Licensed under
the MIT License. See LICENSE in the project root for license information.
-->
<Toolkit:XamlApplication x:Class="TerminalApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:TA="using:TerminalApp"
xmlns:Toolkit="using:Microsoft.Toolkit.Win32.UI.XamlHost"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:TerminalApp"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Application x:Class="TerminalApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:TA="using:TerminalApp"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:TerminalApp"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<!--
If you want to prove this works, then add `RequestedTheme="Light"` to
the properties on the XamlApplication
-->
<Toolkit:XamlApplication.Resources>
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
@@ -202,5 +201,5 @@
</ResourceDictionary>
</Toolkit:XamlApplication.Resources>
</Toolkit:XamlApplication>
</Application.Resources>
</Application>

View File

@@ -235,10 +235,11 @@ namespace winrt::TerminalApp::implementation
}
}
const auto& duplicateFromTab{ realArgs.SplitMode() == SplitType::Duplicate ? _GetFocusedTab() : nullptr };
_SplitPane(realArgs.SplitDirection(),
// This is safe, we're already filtering so the value is (0, 1)
::base::saturated_cast<float>(realArgs.SplitSize()),
_MakePane(realArgs.TerminalArgs(), realArgs.SplitMode() == SplitType::Duplicate));
_MakePane(realArgs.TerminalArgs(), duplicateFromTab));
args.Handled(true);
}
}

View File

@@ -344,16 +344,12 @@ namespace winrt::TerminalApp::implementation
Media::SolidColorBrush hoverTabBrush{};
Media::SolidColorBrush subtleFillColorSecondaryBrush;
Media::SolidColorBrush subtleFillColorTertiaryBrush;
// calculate the luminance of the current color and select a font
// color based on that
// see https://www.w3.org/TR/WCAG20/#relativeluminancedef
if (TerminalApp::ColorHelper::IsBrightColor(color))
{
fontBrush.Color(winrt::Windows::UI::Colors::Black());
auto secondaryFontColor = winrt::Windows::UI::Colors::Black();
// For alpha value see: https://github.com/microsoft/microsoft-ui-xaml/blob/7a33ad772d77d908aa6b316ec24e6d2eb3ebf571/dev/CommonStyles/Common_themeresources_any.xaml#L269
secondaryFontColor.A = 0x9E;
secondaryFontBrush.Color(secondaryFontColor);
auto subtleFillColorSecondary = winrt::Windows::UI::Colors::Black();
subtleFillColorSecondary.A = 0x09;
subtleFillColorSecondaryBrush.Color(subtleFillColorSecondary);
@@ -363,11 +359,6 @@ namespace winrt::TerminalApp::implementation
}
else
{
fontBrush.Color(winrt::Windows::UI::Colors::White());
auto secondaryFontColor = winrt::Windows::UI::Colors::White();
// For alpha value see: https://github.com/microsoft/microsoft-ui-xaml/blob/7a33ad772d77d908aa6b316ec24e6d2eb3ebf571/dev/CommonStyles/Common_themeresources_any.xaml#L14
secondaryFontColor.A = 0xC5;
secondaryFontBrush.Color(secondaryFontColor);
auto subtleFillColorSecondary = winrt::Windows::UI::Colors::White();
subtleFillColorSecondary.A = 0x0F;
subtleFillColorSecondaryBrush.Color(subtleFillColorSecondary);
@@ -376,6 +367,25 @@ namespace winrt::TerminalApp::implementation
subtleFillColorTertiaryBrush.Color(subtleFillColorTertiary);
}
// The tab font should be based on the evaluated appearance of the tab color layered on tab row.
const auto layeredTabColor = til::color{ color }.layer_over(_tabRowColor);
if (TerminalApp::ColorHelper::IsBrightColor(layeredTabColor))
{
fontBrush.Color(winrt::Windows::UI::Colors::Black());
auto secondaryFontColor = winrt::Windows::UI::Colors::Black();
// For alpha value see: https://github.com/microsoft/microsoft-ui-xaml/blob/7a33ad772d77d908aa6b316ec24e6d2eb3ebf571/dev/CommonStyles/Common_themeresources_any.xaml#L269
secondaryFontColor.A = 0x9E;
secondaryFontBrush.Color(secondaryFontColor);
}
else
{
fontBrush.Color(winrt::Windows::UI::Colors::White());
auto secondaryFontColor = winrt::Windows::UI::Colors::White();
// For alpha value see: https://github.com/microsoft/microsoft-ui-xaml/blob/7a33ad772d77d908aa6b316ec24e6d2eb3ebf571/dev/CommonStyles/Common_themeresources_any.xaml#L14
secondaryFontColor.A = 0xC5;
secondaryFontBrush.Color(secondaryFontColor);
}
selectedTabBrush.Color(color);
// Start with the current tab color, set to Opacity=.3

View File

@@ -20,16 +20,11 @@
Height="15"
MinWidth="0"
MinHeight="0"
Margin="-7.5,0,8,0"
Margin="3,0,8,0"
IsActive="{x:Bind TabStatus.IsProgressRingActive, Mode=OneWay}"
IsIndeterminate="{x:Bind TabStatus.IsProgressRingIndeterminate, Mode=OneWay}"
Visibility="{x:Bind TabStatus.IsProgressRingActive, Mode=OneWay}"
Value="{x:Bind TabStatus.ProgressValue, Mode=OneWay}" />
<!--
We want the progress ring to 'replace' the tab icon, but we don't have control
over the tab icon here (the tab view item does) - so we hide the tab icon there
and use a negative margin for the progress ring here to put it where the icon would be
-->
<FontIcon x:Name="HeaderBellIndicator"
Margin="0,0,8,0"
FontFamily="{ThemeResource SymbolThemeFontFamily}"

View File

@@ -86,7 +86,7 @@ namespace winrt::TerminalApp::implementation
//
// This call to _MakePane won't return nullptr, we already checked that
// case above with the _maybeElevate call.
_CreateNewTabFromPane(_MakePane(newTerminalArgs, false, existingConnection));
_CreateNewTabFromPane(_MakePane(newTerminalArgs, nullptr, existingConnection));
return S_OK;
}
CATCH_RETURN();
@@ -337,7 +337,7 @@ namespace winrt::TerminalApp::implementation
// In the future, it may be preferable to just duplicate the
// current control's live settings (which will include changes
// made through VT).
_CreateNewTabFromPane(_MakePane(nullptr, true, nullptr));
_CreateNewTabFromPane(_MakePane(nullptr, tab, nullptr));
const auto runtimeTabText{ tab.GetTabText() };
if (!runtimeTabText.empty())
@@ -360,7 +360,7 @@ namespace winrt::TerminalApp::implementation
try
{
_SetFocusedTab(tab);
_SplitPane(tab, SplitDirection::Automatic, 0.5f, _MakePane(nullptr, true));
_SplitPane(tab, SplitDirection::Automatic, 0.5f, _MakePane(nullptr, tab));
}
CATCH_LOG();
}

View File

@@ -19,7 +19,6 @@
</PropertyGroup>
<PropertyGroup Label="NuGet Dependencies">
<TerminalCppWinrt>true</TerminalCppWinrt>
<TerminalXamlApplicationToolkit>true</TerminalXamlApplicationToolkit>
<TerminalMUX>true</TerminalMUX>
</PropertyGroup>
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
@@ -382,6 +381,14 @@
<Private>false</Private>
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
</Reference>
<Reference Include="$(WindowsSDK_MetadataPathVersioned)\Windows.UI.Xaml.Hosting.HostingContract\*\*.winmd">
<WinMDFile>true</WinMDFile>
<CopyLocal>false</CopyLocal>
<ReferenceGrouping>$(TargetPlatformMoniker)</ReferenceGrouping>
<ReferenceGroupingDisplayName>$(TargetPlatformDisplayName)</ReferenceGroupingDisplayName>
<ResolvedFrom>CppWinRTImplicitlyExpandTargetPlatform</ResolvedFrom>
<IsSystemReference>True</IsSystemReference>
</Reference>
</ItemGroup>
<!-- ====================== Compiler & Linker Flags ===================== -->
<ItemDefinitionGroup>

View File

@@ -1320,6 +1320,29 @@ namespace winrt::TerminalApp::implementation
e.Handled(true);
}
bool TerminalPage::OnDirectKeyEvent(const uint32_t vkey, const uint8_t scanCode, const bool down)
{
const auto modifiers = _GetPressedModifierKeys();
if (vkey == VK_SPACE && modifiers.IsAltPressed() && down)
{
if (const auto actionMap = _settings.ActionMap())
{
if (const auto cmd = actionMap.GetActionByKeyChord({
modifiers.IsCtrlPressed(),
modifiers.IsAltPressed(),
modifiers.IsShiftPressed(),
modifiers.IsWinPressed(),
gsl::narrow_cast<int32_t>(vkey),
scanCode,
}))
{
return _actionDispatch->DoAction(cmd.ActionAndArgs());
}
}
}
return false;
}
// Method Description:
// - Get the modifier keys that are currently pressed. This can be used to
// find out which modifiers (ctrl, alt, shift) are pressed in events that
@@ -2484,8 +2507,8 @@ namespace winrt::TerminalApp::implementation
// - newTerminalArgs: an object that may contain a blob of parameters to
// control which profile is created and with possible other
// configurations. See CascadiaSettings::BuildSettings for more details.
// - duplicate: a boolean to indicate whether the pane we create should be
// a duplicate of the currently focused pane
// - sourceTab: an optional tab reference that indicates that the created
// pane should be a duplicate of the tab's focused pane
// - existingConnection: optionally receives a connection from the outside
// world instead of attempting to create one
// Return Value:
@@ -2493,29 +2516,25 @@ namespace winrt::TerminalApp::implementation
// connection, then we'll return nullptr. Otherwise, we'll return a new
// Pane for this connection.
std::shared_ptr<Pane> TerminalPage::_MakePane(const NewTerminalArgs& newTerminalArgs,
const bool duplicate,
const winrt::TerminalApp::TabBase& sourceTab,
TerminalConnection::ITerminalConnection existingConnection)
{
TerminalSettingsCreateResult controlSettings{ nullptr };
Profile profile{ nullptr };
if (duplicate)
if (const auto& terminalTab{ _GetTerminalTabImpl(sourceTab) })
{
const auto focusedTab{ _GetFocusedTabImpl() };
if (focusedTab)
profile = terminalTab->GetFocusedProfile();
if (profile)
{
profile = focusedTab->GetFocusedProfile();
if (profile)
// TODO GH#5047 If we cache the NewTerminalArgs, we no longer need to do this.
profile = GetClosestProfileForDuplicationOfProfile(profile);
controlSettings = TerminalSettings::CreateWithProfile(_settings, profile, *_bindings);
const auto workingDirectory = terminalTab->GetActiveTerminalControl().WorkingDirectory();
const auto validWorkingDirectory = !workingDirectory.empty();
if (validWorkingDirectory)
{
// TODO GH#5047 If we cache the NewTerminalArgs, we no longer need to do this.
profile = GetClosestProfileForDuplicationOfProfile(profile);
controlSettings = TerminalSettings::CreateWithProfile(_settings, profile, *_bindings);
const auto workingDirectory = focusedTab->GetActiveTerminalControl().WorkingDirectory();
const auto validWorkingDirectory = !workingDirectory.empty();
if (validWorkingDirectory)
{
controlSettings.DefaultSettings().StartingDirectory(workingDirectory);
}
controlSettings.DefaultSettings().StartingDirectory(workingDirectory);
}
}
}
@@ -2587,6 +2606,12 @@ namespace winrt::TerminalApp::implementation
// - <none>
void TerminalPage::_SetBackgroundImage(const winrt::Microsoft::Terminal::Settings::Model::IAppearanceConfig& newAppearance)
{
if (!_settings.GlobalSettings().UseBackgroundImageForWindow())
{
_tabContent.Background(nullptr);
return;
}
const auto path = newAppearance.ExpandedBackgroundImagePath();
if (path.empty())
{
@@ -2624,9 +2649,14 @@ namespace winrt::TerminalApp::implementation
Media::Imaging::BitmapImage image(imageUri);
b.ImageSource(image);
_tabContent.Background(b);
}
b.Stretch(newAppearance.BackgroundImageStretchMode());
b.Opacity(newAppearance.BackgroundImageOpacity());
// Pull this into a separate block. If the image didn't change, but the
// properties of the image did, we should still update them.
if (const auto newBrush{ _tabContent.Background().try_as<Media::ImageBrush>() })
{
newBrush.Stretch(newAppearance.BackgroundImageStretchMode());
newBrush.Opacity(newAppearance.BackgroundImageOpacity());
}
}
@@ -2660,18 +2690,6 @@ namespace winrt::TerminalApp::implementation
profileGuidSettingsMap.insert_or_assign(newProfile.Guid(), std::pair{ newProfile, nullptr });
}
if (_settings.GlobalSettings().UseBackgroundImageForWindow())
{
const auto focusedTab{ _GetFocusedTabImpl() };
if (focusedTab)
{
auto profile = focusedTab->GetFocusedProfile();
if (profile)
{
_SetBackgroundImage(profile.DefaultAppearance());
}
}
}
for (const auto& tab : _tabs)
{
if (auto terminalTab{ _GetTerminalTabImpl(tab) })
@@ -2717,6 +2735,14 @@ namespace winrt::TerminalApp::implementation
tabImpl->SetActionMap(_settings.ActionMap());
}
if (const auto focusedTab{ _GetFocusedTabImpl() })
{
if (const auto profile{ focusedTab->GetFocusedProfile() })
{
_SetBackgroundImage(profile.DefaultAppearance());
}
}
// repopulate the new tab button's flyout with entries for each
// profile, which might have changed
_UpdateTabWidthMode();
@@ -3292,7 +3318,7 @@ namespace winrt::TerminalApp::implementation
// elevated version of the Terminal with that profile... that's a
// recipe for disaster. We won't ever open up a tab in this window.
newTerminalArgs.Elevate(false);
const auto newPane = _MakePane(newTerminalArgs, false, connection);
const auto newPane = _MakePane(newTerminalArgs, nullptr, connection);
newPane->WalkTree([](auto pane) {
pane->FinalizeConfigurationGivenDefault();
});
@@ -3303,6 +3329,22 @@ namespace winrt::TerminalApp::implementation
const IInspectable unused{ nullptr };
_SetAsDefaultDismissHandler(unused, unused);
// TEMPORARY SOLUTION
// If the connection has requested for the window to be maximized,
// manually maximize it here. Ideally, we should be _initializing_
// the session maximized, instead of manually maximizing it after initialization.
// However, because of the current way our defterm handoff works,
// we are unable to get the connection info before the terminal session
// has already started.
// Make sure that there were no other tabs already existing (in
// the case that we are in glomming mode), because we don't want
// to be maximizing other existing sessions that did not ask for it.
if (_tabs.Size() == 1 && connection.ShowWindow() == SW_SHOWMAXIMIZED)
{
RequestSetMaximized(true);
}
return S_OK;
}
CATCH_RETURN()

View File

@@ -136,6 +136,8 @@ namespace winrt::TerminalApp::implementation
void OpenSettingsUI();
void WindowActivated(const bool activated);
bool OnDirectKeyEvent(const uint32_t vkey, const uint8_t scanCode, const bool down);
WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);
// -------------------------------- WinRT Events ---------------------------------
@@ -388,7 +390,7 @@ namespace winrt::TerminalApp::implementation
const winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection& connection);
std::shared_ptr<Pane> _MakePane(const Microsoft::Terminal::Settings::Model::NewTerminalArgs& newTerminalArgs = nullptr,
const bool duplicate = false,
const winrt::TerminalApp::TabBase& sourceTab = nullptr,
winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection existingConnection = nullptr);
void _RefreshUIForSettingsReload();

View File

@@ -1,6 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import "TaskbarState.idl";
import "IDirectKeyListener.idl";
namespace TerminalApp
{
@@ -16,7 +17,7 @@ namespace TerminalApp
Windows.Foundation.IAsyncOperation<Windows.UI.Xaml.Controls.ContentDialogResult> ShowDialog(Windows.UI.Xaml.Controls.ContentDialog dialog);
};
[default_interface] runtimeclass TerminalPage : Windows.UI.Xaml.Controls.Page, Windows.UI.Xaml.Data.INotifyPropertyChanged
[default_interface] runtimeclass TerminalPage : Windows.UI.Xaml.Controls.Page, Windows.UI.Xaml.Data.INotifyPropertyChanged, IDirectKeyListener
{
TerminalPage();

View File

@@ -15,6 +15,7 @@ using namespace winrt::Windows::UI::Xaml;
using namespace winrt::Windows::UI::Core;
using namespace winrt::Microsoft::Terminal::Control;
using namespace winrt::Microsoft::Terminal::Settings::Model;
using namespace winrt::Microsoft::UI::Xaml::Controls;
using namespace winrt::Windows::System;
namespace winrt
@@ -316,7 +317,7 @@ namespace winrt::TerminalApp::implementation
if (hide)
{
Icon({});
TabViewItem().IconSource(IconPathConverter::IconSourceMUX({}));
TabViewItem().IconSource(IconSource{ nullptr });
}
else
{

View File

@@ -14,7 +14,6 @@
</PropertyGroup>
<PropertyGroup Label="NuGet Dependencies">
<TerminalCppWinrt>true</TerminalCppWinrt>
<TerminalXamlApplicationToolkit>true</TerminalXamlApplicationToolkit>
<TerminalMUX>true</TerminalMUX>
</PropertyGroup>
<Import Project="..\..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.UI.Xaml" version="2.7.2-prerelease.220406002" targetFramework="native" />
<package id="Microsoft.UI.Xaml" version="2.7.3-prerelease.220816001" targetFramework="native" />
</packages>

View File

@@ -50,7 +50,6 @@
#include <winrt/Windows.Media.Core.h>
#include <winrt/Windows.Media.Playback.h>
#include <winrt/Microsoft.Toolkit.Win32.UI.XamlHost.h>
#include <winrt/Microsoft.UI.Xaml.Controls.h>
#include <winrt/Microsoft.UI.Xaml.Controls.Primitives.h>
#include <winrt/Microsoft.UI.Xaml.XamlTypeInfo.h>

View File

@@ -215,10 +215,9 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
_piClient.hProcess = hClientProcess;
_startupInfo.title = winrt::hstring{ startupInfo.pszTitle, SysStringLen(startupInfo.pszTitle) };
SysFreeString(startupInfo.pszTitle);
_startupInfo.iconPath = winrt::hstring{ startupInfo.pszIconPath, SysStringLen(startupInfo.pszIconPath) };
SysFreeString(startupInfo.pszIconPath);
_startupInfo.iconIndex = startupInfo.iconIndex;
_startupInfo.showWindow = startupInfo.wShowWindow;
try
{
@@ -300,6 +299,11 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
return _startupInfo.title;
}
WORD ConptyConnection::ShowWindow() const noexcept
{
return _startupInfo.showWindow;
}
void ConptyConnection::Start()
try
{
@@ -554,6 +558,15 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
_hPC.reset(); // tear down the pseudoconsole (this is like clicking X on a console window)
// CloseHandle() on pipes blocks until any current WriteFile()/ReadFile() has returned.
// CancelSynchronousIo prevents us from deadlocking ourselves.
// At this point in Close(), _inPipe won't be used anymore since the UI parts are torn down.
// _outPipe is probably still stuck in ReadFile() and might currently be written to.
if (_hOutputThread)
{
CancelSynchronousIo(_hOutputThread.get());
}
_inPipe.reset(); // break the pipes
_outPipe.reset();
@@ -615,10 +628,17 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
DWORD read{};
const auto readFail{ !ReadFile(_outPipe.get(), _buffer.data(), gsl::narrow_cast<DWORD>(_buffer.size()), &read, nullptr) };
// When we call CancelSynchronousIo() in Close() this is the branch that's taken and gets us out of here.
if (_isStateAtOrBeyond(ConnectionState::Closing))
{
return 0;
}
if (readFail) // reading failed (we must check this first, because read will also be 0.)
{
const auto lastError = GetLastError();
if (lastError != ERROR_BROKEN_PIPE && !_isStateAtOrBeyond(ConnectionState::Closing))
if (lastError != ERROR_BROKEN_PIPE)
{
// EXIT POINT
_indicateExitWithStatus(HRESULT_FROM_WIN32(lastError)); // print a message
@@ -631,12 +651,6 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
const auto result{ til::u8u16(std::string_view{ _buffer.data(), read }, _u16Str, _u8State) };
if (FAILED(result))
{
if (_isStateAtOrBeyond(ConnectionState::Closing))
{
// This termination was expected.
return 0;
}
// EXIT POINT
_indicateExitWithStatus(result); // print a message
_transitionToState(ConnectionState::Failed);

View File

@@ -13,7 +13,7 @@
namespace wil
{
// These belong in WIL upstream, so when we reingest the change that has them we'll get rid of ours.
using unique_static_pseudoconsole_handle = wil::unique_any<HPCON, decltype(&::ConptyClosePseudoConsole), ::ConptyClosePseudoConsole>;
using unique_static_pseudoconsole_handle = wil::unique_any<HPCON, decltype(&::ConptyClosePseudoConsole), ::ConptyClosePseudoConsoleNoWait>;
}
namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
@@ -46,6 +46,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
winrt::guid Guid() const noexcept;
winrt::hstring Commandline() const;
winrt::hstring StartingTitle() const;
WORD ShowWindow() const noexcept;
static void StartInboundListener();
static void StopInboundListener();
@@ -102,6 +103,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
winrt::hstring title{};
winrt::hstring iconPath{};
int32_t iconIndex{};
WORD showWindow{};
} _startupInfo{};

View File

@@ -13,6 +13,7 @@ namespace Microsoft.Terminal.TerminalConnection
Guid Guid { get; };
String Commandline { get; };
String StartingTitle { get; };
UInt16 ShowWindow { get; };
void ClearBuffer();

View File

@@ -4,6 +4,10 @@
#include "pch.h"
#include "ControlCore.h"
// MidiAudio
#include <mmeapi.h>
#include <dsound.h>
#include <DefaultSettings.h>
#include <unicode.hpp>
#include <Utf16Parser.hpp>
@@ -95,7 +99,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
Control::IControlAppearance unfocusedAppearance,
TerminalConnection::ITerminalConnection connection) :
_connection{ connection },
_desiredFont{ DEFAULT_FONT_FACE, 0, DEFAULT_FONT_WEIGHT, { 0, DEFAULT_FONT_SIZE }, CP_UTF8 },
_desiredFont{ DEFAULT_FONT_FACE, 0, DEFAULT_FONT_WEIGHT, DEFAULT_FONT_SIZE, CP_UTF8 },
_actualFont{ DEFAULT_FONT_FACE, 0, DEFAULT_FONT_WEIGHT, { 0, DEFAULT_FONT_SIZE }, CP_UTF8, false }
{
_EnsureStaticInitialization();
@@ -241,8 +245,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
{
_renderer->TriggerTeardown();
}
_shutdownMidiAudio();
}
bool ControlCore::Initialize(const double actualWidth,
@@ -401,9 +403,33 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const WORD scanCode,
const ::Microsoft::Terminal::Core::ControlKeyStates modifiers)
{
if (ch == L'\x3') // Ctrl+C or Ctrl+Break
{
_handleControlC();
}
return _terminal->SendCharEvent(ch, scanCode, modifiers);
}
void ControlCore::_handleControlC()
{
if (!_midiAudioSkipTimer)
{
_midiAudioSkipTimer = _dispatcher.CreateTimer();
_midiAudioSkipTimer.Interval(std::chrono::seconds(1));
_midiAudioSkipTimer.IsRepeating(false);
_midiAudioSkipTimer.Tick([weakSelf = get_weak()](auto&&, auto&&) {
if (const auto self = weakSelf.get())
{
self->_midiAudio.EndSkip();
}
});
}
_midiAudio.BeginSkip();
_midiAudioSkipTimer.Start();
}
bool ControlCore::_shouldTryUpdateSelection(const WORD vkey)
{
// GH#6423 - don't update selection if the key that was pressed was a
@@ -576,18 +602,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
// Update our runtime opacity value
Opacity(newOpacity);
_runtimeOpacity = newOpacity;
// GH#11285 - If the user is on Windows 10, and they changed the
// transparency of the control s.t. it should be partially opaque, then
// opt them in to acrylic. It's the only way to have transparency on
// Windows 10.
// We'll also turn the acrylic back off when they're fully opaque, which
// is what the Terminal did prior to 1.12.
if (!IsVintageOpacityAvailable())
{
_runtimeUseAcrylic = newOpacity < 1.0;
}
// Manually turn off acrylic if they turn off transparency.
_runtimeUseAcrylic = newOpacity < 1.0 && _settings->UseAcrylic();
// Update the renderer as well. It might need to fall back from
// cleartype -> grayscale if the BG is transparent / acrylic.
@@ -692,7 +710,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
auto lock = _terminal->LockForReading(); // Lock for the duration of our reads.
if (_lastHoveredCell.has_value())
{
return winrt::hstring{ _terminal->GetHyperlinkAtViewportPosition(*_lastHoveredCell) };
auto uri{ _terminal->GetHyperlinkAtViewportPosition(*_lastHoveredCell) };
uri.resize(std::min<size_t>(1024u, uri.size())); // Truncate for display
return winrt::hstring{ uri };
}
return {};
}
@@ -712,15 +732,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
auto lock = _terminal->LockForWriting();
_runtimeOpacity = std::nullopt;
_runtimeUseAcrylic = std::nullopt;
// GH#11285 - If the user is on Windows 10, and they wanted opacity, but
// didn't explicitly request acrylic, then opt them in to acrylic.
// On Windows 11+, this isn't needed, because we can have vintage opacity.
if (!IsVintageOpacityAvailable() && _settings->Opacity() < 1.0 && !_settings->UseAcrylic())
{
_runtimeUseAcrylic = true;
}
// Manually turn off acrylic if they turn off transparency.
_runtimeUseAcrylic = _settings->Opacity() < 1.0 && _settings->UseAcrylic();
const auto sizeChanged = _setFontSizeUnderLock(_settings->FontSize());
@@ -859,15 +873,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - fontSize: The size of the font.
// Return Value:
// - Returns true if you need to call _refreshSizeUnderLock().
bool ControlCore::_setFontSizeUnderLock(int fontSize)
bool ControlCore::_setFontSizeUnderLock(float fontSize)
{
// Make sure we have a non-zero font size
const auto newSize = std::max(fontSize, 1);
const auto newSize = std::max(fontSize, 1.0f);
const auto fontFace = _settings->FontFace();
const auto fontWeight = _settings->FontWeight();
_actualFont = { fontFace, 0, fontWeight.Weight, { 0, newSize }, CP_UTF8, false };
_desiredFont = { fontFace, 0, fontWeight.Weight, newSize, CP_UTF8 };
_actualFont = { fontFace, 0, fontWeight.Weight, _desiredFont.GetEngineSize(), CP_UTF8, false };
_actualFontFaceName = { fontFace };
_desiredFont = { _actualFont };
const auto before = _actualFont.GetSize();
_updateFont();
@@ -893,11 +907,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - Adjust the font size of the terminal control.
// Arguments:
// - fontSizeDelta: The amount to increase or decrease the font size by.
void ControlCore::AdjustFontSize(int fontSizeDelta)
void ControlCore::AdjustFontSize(float fontSizeDelta)
{
const auto lock = _terminal->LockForWriting();
if (_setFontSizeUnderLock(_desiredFont.GetEngineSize().Y + fontSizeDelta))
if (_setFontSizeUnderLock(_desiredFont.GetFontSize() + fontSizeDelta))
{
_refreshSizeUnderLock();
}
@@ -1211,10 +1225,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation
return static_cast<uint16_t>(_actualFont.GetWeight());
}
til::size ControlCore::FontSizeInDips() const
winrt::Windows::Foundation::Size ControlCore::FontSizeInDips() const
{
const til::size fontSize{ _actualFont.GetSize() };
return fontSize.scale(til::math::rounding, 1.0f / ::base::saturated_cast<float>(_compositionScale));
const auto fontSize = _actualFont.GetSize();
const auto scale = 1.0f / static_cast<float>(_compositionScale);
return {
fontSize.width * scale,
fontSize.height * scale,
};
}
TerminalConnection::ConnectionState ControlCore::ConnectionState() const
@@ -1387,57 +1405,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - duration - How long the note should be sustained (in microseconds).
void ControlCore::_terminalPlayMidiNote(const int noteNumber, const int velocity, const std::chrono::microseconds duration)
{
// We create the audio instance on demand, and lock it for the duration
// of the note output so it can't be destroyed while in use.
auto& midiAudio = _getMidiAudio();
midiAudio.Lock();
// We then unlock the terminal, so the UI doesn't hang while we're busy.
// Unlock the terminal, so the UI doesn't hang while we're busy.
auto& terminalLock = _terminal->GetReadWriteLock();
terminalLock.unlock();
// This call will block for the duration, unless shutdown early.
midiAudio.PlayNote(noteNumber, velocity, duration);
_midiAudio.PlayNote(reinterpret_cast<HWND>(_owningHwnd), noteNumber, velocity, std::chrono::duration_cast<std::chrono::milliseconds>(duration));
// Once complete, we reacquire the terminal lock and unlock the audio.
// If the terminal has shutdown in the meantime, the Unlock call
// will throw an exception, forcing the thread to exit ASAP.
terminalLock.lock();
midiAudio.Unlock();
}
// Method Description:
// - Returns the MIDI audio instance, created on demand.
// Arguments:
// - <none>
// Return Value:
// - a reference to the MidiAudio instance.
MidiAudio& ControlCore::_getMidiAudio()
{
if (!_midiAudio)
{
const auto windowHandle = reinterpret_cast<HWND>(_owningHwnd);
_midiAudio = std::make_unique<MidiAudio>(windowHandle);
_midiAudio->Initialize();
}
return *_midiAudio;
}
// Method Description:
// - Shuts down the MIDI audio system if previously instantiated.
// Arguments:
// - <none>
// Return Value:
// - <none>
void ControlCore::_shutdownMidiAudio()
{
if (_midiAudio)
{
// We lock the terminal here to make sure the shutdown promise is
// set before the audio is unlocked in the thread that is playing.
auto lock = _terminal->LockForWriting();
_midiAudio->Shutdown();
}
}
bool ControlCore::HasSelection() const
@@ -1522,6 +1497,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
{
_closing = true;
// Ensure Close() doesn't hang, waiting for MidiAudio to finish playing an hour long song.
_midiAudio.BeginSkip();
// Stop accepting new output and state changes before we disconnect everything.
_connection.TerminalOutput(_connectionOutputEventToken);
_connectionStateChangedRevoker.revoke();
@@ -1774,22 +1752,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
return hstring(ss.str());
}
// Helper to check if we're on Windows 11 or not. This is used to check if
// we need to use acrylic to achieve transparency, because vintage opacity
// doesn't work in islands on win10.
// Remove when we can remove the rest of GH#11285
bool ControlCore::IsVintageOpacityAvailable() noexcept
{
OSVERSIONINFOEXW osver{};
osver.dwOSVersionInfoSize = sizeof(osver);
osver.dwBuildNumber = 22000;
DWORDLONG dwlConditionMask = 0;
VER_SET_CONDITION(dwlConditionMask, VER_BUILDNUMBER, VER_GREATER_EQUAL);
return VerifyVersionInfoW(&osver, VER_BUILDNUMBER, dwlConditionMask) != FALSE;
}
Core::Scheme ControlCore::ColorScheme() const noexcept
{
Core::Scheme s;
@@ -1968,13 +1930,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation
{
// If we're:
// * Not fully opaque
// * On an acrylic background (of any opacity)
// * rendering on top of an image
//
// then the renderer should not render "default background" text with a
// fully opaque background. Doing that would cover up our nice
// transparency, or our acrylic, or our image.
return Opacity() < 1.0f || UseAcrylic() || !_settings->BackgroundImage().empty() || _settings->UseBackgroundImageForWindow();
return Opacity() < 1.0f || !_settings->BackgroundImage().empty() || _settings->UseBackgroundImageForWindow();
}
uint64_t ControlCore::OwningHwnd()

View File

@@ -76,10 +76,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void SizeChanged(const double width, const double height);
void ScaleChanged(const double scale);
void AdjustFontSize(int fontSizeDelta);
void AdjustFontSize(float fontSizeDelta);
void ResetFontSize();
FontInfo GetFont() const;
til::size FontSizeInDips() const;
winrt::Windows::Foundation::Size FontSizeInDips() const;
winrt::Windows::Foundation::Size FontSize() const noexcept;
winrt::hstring FontFaceName() const noexcept;
@@ -282,12 +282,13 @@ namespace winrt::Microsoft::Terminal::Control::implementation
std::unique_ptr<til::throttled_func_trailing<>> _updatePatternLocations;
std::shared_ptr<ThrottledFuncTrailing<Control::ScrollPositionChangedArgs>> _updateScrollBar;
bool _setFontSizeUnderLock(int fontSize);
bool _setFontSizeUnderLock(float fontSize);
void _updateFont(const bool initialUpdate = false);
void _refreshSizeUnderLock();
void _updateSelectionUI();
bool _shouldTryUpdateSelection(const WORD vkey);
void _handleControlC();
void _sendInputToConnection(std::wstring_view wstr);
#pragma region TerminalCoreCallbacks
@@ -305,10 +306,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const std::chrono::microseconds duration);
#pragma endregion
std::unique_ptr<MidiAudio> _midiAudio;
MidiAudio& _getMidiAudio();
void _shutdownMidiAudio();
MidiAudio _midiAudio;
winrt::Windows::System::DispatcherQueueTimer _midiAudioSkipTimer{ nullptr };
#pragma region RendererCallbacks
void _rendererWarning(const HRESULT hr);

View File

@@ -105,7 +105,7 @@ namespace Microsoft.Terminal.Control
void ClearHoveredCell();
void ResetFontSize();
void AdjustFontSize(Int32 fontSizeDelta);
void AdjustFontSize(Single fontSizeDelta);
void SizeChanged(Double width, Double height);
void ScaleChanged(Double scale);

View File

@@ -301,7 +301,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const auto touchdownPoint = *_singleClickTouchdownPos;
const auto dx = pixelPosition.X - touchdownPoint.X;
const auto dy = pixelPosition.Y - touchdownPoint.Y;
const auto w = fontSizeInDips.width;
const auto w = fontSizeInDips.Width;
const auto distanceSquared = dx * dx + dy * dy;
const auto maxDistanceSquared = w * w / 16; // (w / 4)^2
@@ -337,16 +337,16 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const auto fontSizeInDips{ _core->FontSizeInDips() };
// Get the difference between the point we've dragged to and the start of the touch.
const auto dy = static_cast<double>(newTouchPoint.Y - anchor.Y);
const auto dy = static_cast<float>(newTouchPoint.Y - anchor.Y);
// Start viewport scroll after we've moved more than a half row of text
if (std::abs(dy) > (fontSizeInDips.height / 2.0))
if (std::abs(dy) > (fontSizeInDips.Height / 2.0f))
{
// Multiply by -1, because moving the touch point down will
// create a positive delta, but we want the viewport to move up,
// so we'll need a negative scroll amount (and the inverse for
// panning down)
const auto numRows = dy / -fontSizeInDips.height;
const auto numRows = dy / -fontSizeInDips.Height;
const auto currentOffset = _core->ScrollOffset();
const auto newValue = numRows + currentOffset;
@@ -459,7 +459,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// scrolling event.
// Arguments:
// - mouseDelta: the mouse wheel delta that triggered this event.
void ControlInteractivity::_mouseTransparencyHandler(const double mouseDelta)
void ControlInteractivity::_mouseTransparencyHandler(const int32_t mouseDelta) const
{
// Transparency is on a scale of [0.0,1.0], so only increment by .01.
const auto effectiveDelta = mouseDelta < 0 ? -.01 : .01;
@@ -471,9 +471,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// event.
// Arguments:
// - mouseDelta: the mouse wheel delta that triggered this event.
void ControlInteractivity::_mouseZoomHandler(const double mouseDelta)
void ControlInteractivity::_mouseZoomHandler(const int32_t mouseDelta) const
{
const auto fontDelta = mouseDelta < 0 ? -1 : 1;
const auto fontDelta = mouseDelta < 0 ? -1.0f : 1.0f;
_core->AdjustFontSize(fontDelta);
}
@@ -483,7 +483,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - mouseDelta: the mouse wheel delta that triggered this event.
// - pixelPosition: the location of the mouse during this event
// - isLeftButtonPressed: true iff the left mouse button was pressed during this event.
void ControlInteractivity::_mouseScrollHandler(const double mouseDelta,
void ControlInteractivity::_mouseScrollHandler(const int32_t mouseDelta,
const Core::Point pixelPosition,
const bool isLeftButtonPressed)
{

View File

@@ -132,9 +132,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
unsigned int _numberOfClicks(Core::Point clickPos, Timestamp clickTime);
void _updateSystemParameterSettings() noexcept;
void _mouseTransparencyHandler(const double mouseDelta);
void _mouseZoomHandler(const double mouseDelta);
void _mouseScrollHandler(const double mouseDelta,
void _mouseTransparencyHandler(const int32_t mouseDelta) const;
void _mouseZoomHandler(const int32_t mouseDelta) const;
void _mouseScrollHandler(const int32_t mouseDelta,
const Core::Point terminalPosition,
const bool isLeftButtonPressed);

View File

@@ -36,7 +36,7 @@ namespace Microsoft.Terminal.Control
Boolean UseAtlasEngine { get; };
String FontFace { get; };
Int32 FontSize { get; };
Single FontSize { get; };
Windows.UI.Text.FontWeight FontWeight { get; };
String Padding { get; };
Windows.Foundation.Collections.IMap<String, UInt32> FontFeatures { get; };

View File

@@ -26,6 +26,7 @@ using namespace winrt::Windows::UI::ViewManagement;
using namespace winrt::Windows::UI::Input;
using namespace winrt::Windows::System;
using namespace winrt::Windows::ApplicationModel::DataTransfer;
using namespace winrt::Windows::Storage::Streams;
// The minimum delay between updates to the scroll bar's values.
// The updates are throttled to limit power usage.
@@ -1517,7 +1518,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - Adjust the font size of the terminal control.
// Arguments:
// - fontSizeDelta: The amount to increase or decrease the font size by.
void TermControl::AdjustFontSize(int fontSizeDelta)
void TermControl::AdjustFontSize(float fontSizeDelta)
{
_core.AdjustFontSize(fontSizeDelta);
}
@@ -1982,6 +1983,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
if (!_IsClosing())
{
_closing = true;
if (_automationPeer)
{
auto autoPeerImpl{ winrt::get_self<implementation::TermControlAutomationPeer>(_automationPeer) };
autoPeerImpl->Close();
}
_RestorePointerCursorHandlers(*this, nullptr);
@@ -2082,8 +2088,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// The family is only used to determine if the font is truetype or
// not, but DX doesn't use that info at all.
// The Codepage is additionally not actually used by the DX engine at all.
FontInfo actualFont = { fontFace, 0, fontWeight.Weight, { 0, fontSize }, CP_UTF8, false };
FontInfoDesired desiredFont = { actualFont };
FontInfoDesired desiredFont{ fontFace, 0, fontWeight.Weight, fontSize, CP_UTF8 };
FontInfo actualFont{ fontFace, 0, fontWeight.Weight, desiredFont.GetEngineSize(), CP_UTF8, false };
// Create a DX engine and initialize it with our font and DPI. We'll
// then use it to measure how much space the requested rows and columns
@@ -2508,17 +2514,58 @@ namespace winrt::Microsoft::Terminal::Control::implementation
if (items.Size() > 0)
{
std::wstring allPaths;
for (auto item : items)
std::vector<std::wstring> fullPaths;
// GH#14628: Workaround for GetStorageItemsAsync() only returning 16 items
// at most when dragging and dropping from archives (zip, 7z, rar, etc.)
if (items.Size() == 16 && e.DataView().Contains(winrt::hstring{ L"FileDrop" }))
{
auto fileDropData = co_await e.DataView().GetDataAsync(winrt::hstring{ L"FileDrop" });
if (fileDropData != nullptr)
{
auto stream = fileDropData.as<IRandomAccessStream>();
stream.Seek(0);
const uint32_t streamSize = gsl::narrow_cast<uint32_t>(stream.Size());
const Buffer buf(streamSize);
const auto buffer = co_await stream.ReadAsync(buf, streamSize, InputStreamOptions::None);
const HGLOBAL hGlobal = buffer.data();
const auto count = DragQueryFileW(static_cast<HDROP>(hGlobal), 0xFFFFFFFF, nullptr, 0);
fullPaths.reserve(count);
for (unsigned int i = 0; i < count; i++)
{
std::wstring path;
path.resize(wil::max_path_length);
const auto charsCopied = DragQueryFileW(static_cast<HDROP>(hGlobal), i, path.data(), wil::max_path_length);
if (charsCopied > 0)
{
path.resize(charsCopied);
fullPaths.emplace_back(std::move(path));
}
}
}
}
else
{
fullPaths.reserve(items.Size());
for (const auto& item : items)
{
fullPaths.emplace_back(item.Path());
}
}
std::wstring allPathsString;
for (auto& fullPath : fullPaths)
{
// Join the paths with spaces
if (!allPaths.empty())
if (!allPathsString.empty())
{
allPaths += L" ";
allPathsString += L" ";
}
std::wstring fullPath{ item.Path() };
// Fix path for WSL
// In the fullness of time, we should likely plumb this up
// to the TerminalApp layer, and have it make the decision
@@ -2573,10 +2620,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
fullPath += L"\"";
}
allPaths += fullPath;
allPathsString += fullPath;
}
_core.PasteText(winrt::hstring{ allPaths });
_core.PasteText(winrt::hstring{ allPathsString });
}
}
}

View File

@@ -82,7 +82,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void ScrollViewport(int viewTop);
void AdjustFontSize(int fontSizeDelta);
void AdjustFontSize(float fontSizeDelta);
void ResetFontSize();
til::point GetFontSize() const;

View File

@@ -71,7 +71,7 @@ namespace Microsoft.Terminal.Control
void SearchMatch(Boolean goForward);
void AdjustFontSize(Int32 fontSizeDelta);
void AdjustFontSize(Single fontSizeDelta);
void ResetFontSize();
void ToggleShaderEffects();

View File

@@ -112,11 +112,18 @@ namespace winrt::Microsoft::Terminal::Control::implementation
{
if (const auto keyEventChar{ gsl::narrow_cast<wchar_t>(charCode) }; IsReadable({ &keyEventChar, 1 }))
{
_keyEvents.emplace_back(keyEventChar);
_keyEvents.lock()->emplace_back(keyEventChar);
}
}
}
void TermControlAutomationPeer::Close()
{
// GH#13978: If the TermControl has already been removed from the UI tree, XAML might run into weird bugs.
// This will prevent the `dispatcher.RunAsync` calls below from raising UIA events on the main thread.
_termControl = {};
}
// Method Description:
// - Signals the ui automation client that the terminal's selection has changed and should be updated
// Arguments:
@@ -202,27 +209,30 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void TermControlAutomationPeer::NotifyNewOutput(std::wstring_view newOutput)
{
// Try to suppress any events (or event data)
// that is just the keypress the user made
auto sanitized{ Sanitize(newOutput) };
while (!_keyEvents.empty() && IsReadable(sanitized))
// Try to suppress any events (or event data)
// that are just the keypresses the user made
{
if (til::toupper_ascii(sanitized.front()) == _keyEvents.front())
auto keyEvents = _keyEvents.lock();
while (!keyEvents->empty() && IsReadable(sanitized))
{
// the key event's character (i.e. the "A" key) matches
// the output character (i.e. "a" or "A" text).
// We can assume that the output character resulted from
// the pressed key, so we can ignore it.
sanitized = sanitized.substr(1);
_keyEvents.pop_front();
}
else
{
// The output doesn't match,
// so clear the input stack and
// move on to fire the event.
_keyEvents.clear();
break;
if (til::toupper_ascii(sanitized.front()) == keyEvents->front())
{
// the key event's character (i.e. the "A" key) matches
// the output character (i.e. "a" or "A" text).
// We can assume that the output character resulted from
// the pressed key, so we can ignore it.
sanitized = sanitized.substr(1);
keyEvents->pop_front();
}
else
{
// The output doesn't match,
// so clear the input stack and
// move on to fire the event.
keyEvents->clear();
break;
}
}
}

View File

@@ -49,6 +49,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void UpdateControlBounds();
void SetControlPadding(const Core::Padding padding);
void RecordKeyEvent(const WORD vkey);
void Close();
#pragma region FrameworkElementAutomationPeer
hstring GetClassNameCore() const;
@@ -80,6 +81,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
private:
winrt::weak_ref<Microsoft::Terminal::Control::implementation::TermControl> _termControl;
Control::InteractivityAutomationPeer _contentAutomationPeer;
std::deque<wchar_t> _keyEvents;
til::shared_mutex<std::deque<wchar_t>> _keyEvents;
};
}

View File

@@ -88,7 +88,7 @@
<ItemDefinitionGroup>
<Link>
<AdditionalDependencies>dwrite.lib;dxgi.lib;d2d1.lib;d3d11.lib;shcore.lib;winmm.lib;pathcch.lib;propsys.lib;uiautomationcore.lib;Shlwapi.lib;ntdll.lib;user32.lib;kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>dwrite.lib;dxgi.lib;d2d1.lib;d3d11.lib;shcore.lib;winmm.lib;pathcch.lib;propsys.lib;uiautomationcore.lib;Shlwapi.lib;ntdll.lib;user32.lib;shell32.lib;kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<!--
ControlLib contains a DllMain that we need to force the use of.
If you don't have this, then you'll see an error like

View File

@@ -5,6 +5,9 @@
#include <LibraryResources.h>
#include <WilErrorReporting.h>
// For g_hCTerminalCoreProvider
#include "../../cascadia/TerminalCore/tracing.hpp"
// Note: Generate GUID using TlgGuid.exe tool
TRACELOGGING_DEFINE_PROVIDER(
g_hTerminalControlProvider,
@@ -20,6 +23,7 @@ BOOL WINAPI DllMain(HINSTANCE hInstDll, DWORD reason, LPVOID /*reserved*/)
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hInstDll);
TraceLoggingRegister(g_hTerminalControlProvider);
TraceLoggingRegister(g_hCTerminalCoreProvider);
Microsoft::Console::ErrorReporting::EnableFallbackFailureReporting(g_hTerminalControlProvider);
break;
case DLL_PROCESS_DETACH:

View File

@@ -48,6 +48,7 @@
#include <winrt/Windows.ui.xaml.shapes.h>
#include <winrt/Windows.ApplicationModel.DataTransfer.h>
#include <winrt/Windows.Storage.h>
#include <winrt/Windows.Storage.Streams.h>
#include <winrt/Windows.UI.Xaml.Shapes.h>
#include <winrt/Microsoft.Terminal.TerminalConnection.h>
@@ -59,10 +60,12 @@
TRACELOGGING_DECLARE_PROVIDER(g_hTerminalControlProvider);
#include <telemetry/ProjectTelemetry.h>
#include <shellapi.h>
#include <ShlObj_core.h>
#include <WinUser.h>
#include "til.h"
#include <til/mutex.h>
#include "ThrottledFunc.h"

View File

@@ -37,24 +37,7 @@ static std::wstring _KeyEventsToText(std::deque<std::unique_ptr<IInputEvent>>& i
}
#pragma warning(suppress : 26455) // default constructor is throwing, too much effort to rearrange at this time.
Terminal::Terminal() :
_mutableViewport{ Viewport::Empty() },
_title{},
_pfnWriteInput{ nullptr },
_altBuffer{ nullptr },
_scrollOffset{ 0 },
_snapOnInput{ true },
_altGrAliasing{ true },
_blockSelection{ false },
_selectionMode{ SelectionInteractionMode::None },
_selectionIsTargetingUrl{ false },
_selection{ std::nullopt },
_selectionEndpoint{ static_cast<SelectionEndpoint>(0) },
_anchorInactiveSelectionEndpoint{ false },
_taskbarState{ 0 },
_taskbarProgress{ 0 },
_trimBlockSelection{ false },
_autoMarkPrompts{ false }
Terminal::Terminal()
{
auto passAlongInput = [&](std::deque<std::unique_ptr<IInputEvent>>& inEventsToWrite) {
if (!_pfnWriteInput)
@@ -91,7 +74,7 @@ void Terminal::Create(til::size viewportSize, til::CoordType scrollbackLines, Re
// But if they are being accepted by conhost, there's a chance they may get
// passed through in some situations, so it's important that our state
// machine is always prepared to accept them.
_stateMachine->SetParserMode(StateMachine::Mode::AcceptC1, true);
_stateMachine->SetParserMode(StateMachine::Mode::AlwaysAcceptC1, true);
}
// Method Description:

View File

@@ -64,11 +64,6 @@ class Microsoft::Terminal::Core::Terminal final :
public:
Terminal();
~Terminal(){};
Terminal(const Terminal&) = default;
Terminal(Terminal&&) = default;
Terminal& operator=(const Terminal&) = default;
Terminal& operator=(Terminal&&) = default;
void Create(til::size viewportSize,
til::CoordType scrollbackLines,
@@ -272,6 +267,7 @@ public:
enum class SelectionEndpoint
{
None = 0,
Start = 0x1,
End = 0x2
};
@@ -328,19 +324,19 @@ private:
std::wstring _startingTitle;
std::optional<til::color> _startingTabColor;
CursorType _defaultCursorShape;
CursorType _defaultCursorShape = CursorType::Legacy;
bool _snapOnInput;
bool _altGrAliasing;
bool _suppressApplicationTitle;
bool _bracketedPasteMode;
bool _trimBlockSelection;
bool _autoMarkPrompts;
bool _snapOnInput = true;
bool _altGrAliasing = true;
bool _suppressApplicationTitle = false;
bool _bracketedPasteMode = false;
bool _trimBlockSelection = false;
bool _autoMarkPrompts = false;
size_t _taskbarState;
size_t _taskbarProgress;
size_t _taskbarState = 0;
size_t _taskbarProgress = 0;
size_t _hyperlinkPatternId;
size_t _hyperlinkPatternId = 0;
std::wstring _workingDirectory;
@@ -359,27 +355,27 @@ private:
til::point pivot;
};
std::optional<SelectionAnchors> _selection;
bool _blockSelection;
bool _blockSelection = false;
std::wstring _wordDelimiters;
SelectionExpansion _multiClickSelectionMode;
SelectionInteractionMode _selectionMode;
bool _selectionIsTargetingUrl;
SelectionEndpoint _selectionEndpoint;
bool _anchorInactiveSelectionEndpoint;
SelectionExpansion _multiClickSelectionMode = SelectionExpansion::Char;
SelectionInteractionMode _selectionMode = SelectionInteractionMode::None;
bool _selectionIsTargetingUrl = false;
SelectionEndpoint _selectionEndpoint = SelectionEndpoint::None;
bool _anchorInactiveSelectionEndpoint = false;
#pragma endregion
std::unique_ptr<TextBuffer> _mainBuffer;
std::unique_ptr<TextBuffer> _altBuffer;
Microsoft::Console::Types::Viewport _mutableViewport;
til::CoordType _scrollbackLines;
bool _detectURLs{ false };
til::CoordType _scrollbackLines = 0;
bool _detectURLs = false;
til::size _altBufferSize;
std::optional<til::size> _deferredResize{ std::nullopt };
std::optional<til::size> _deferredResize;
// _scrollOffset is the number of lines above the viewport that are currently visible
// If _scrollOffset is 0, then the visible region of the buffer is the viewport.
int _scrollOffset;
til::CoordType _scrollOffset = 0;
// TODO this might not be the value we want to store.
// We might want to store the height in the scrollback that's currently visible.
// Think on this some more.

View File

@@ -3,6 +3,8 @@
#include "pch.h"
#include "Terminal.hpp"
#include "tracing.hpp"
#include "../src/inc/unicode.hpp"
using namespace Microsoft::Terminal::Core;
@@ -10,6 +12,14 @@ using namespace Microsoft::Console::Render;
using namespace Microsoft::Console::Types;
using namespace Microsoft::Console::VirtualTerminal;
// Note: Generate GUID using TlgGuid.exe tool
#pragma warning(suppress : 26477) // One of the macros uses 0/NULL. We don't have control to make it nullptr.
TRACELOGGING_DEFINE_PROVIDER(g_hCTerminalCoreProvider,
"Microsoft.Terminal.Core",
// {103ac8cf-97d2-51aa-b3ba-5ffd5528fa5f}
(0x103ac8cf, 0x97d2, 0x51aa, 0xb3, 0xba, 0x5f, 0xfd, 0x55, 0x28, 0xfa, 0x5f),
TraceLoggingOptionMicrosoftTelemetry());
// Print puts the text in the buffer and moves the cursor
void Terminal::PrintString(const std::wstring_view string)
{
@@ -185,6 +195,19 @@ void Terminal::SetTaskbarProgress(const ::Microsoft::Console::VirtualTerminal::D
void Terminal::SetWorkingDirectory(std::wstring_view uri)
{
static bool logged = false;
if (!logged)
{
TraceLoggingWrite(
g_hCTerminalCoreProvider,
"ShellIntegrationWorkingDirSet",
TraceLoggingDescription("The CWD was set by the client application"),
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
logged = true;
}
_workingDirectory = uri;
}
@@ -300,6 +323,19 @@ void Terminal::UseMainScreenBuffer()
void Terminal::AddMark(const Microsoft::Console::VirtualTerminal::DispatchTypes::ScrollMark& mark)
{
static bool logged = false;
if (!logged)
{
TraceLoggingWrite(
g_hCTerminalCoreProvider,
"ShellIntegrationMarkAdded",
TraceLoggingDescription("A mark was added via VT at least once"),
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
logged = true;
}
const til::point cursorPos{ _activeBuffer().GetCursor().GetPosition() };
AddMark(mark, cursorPos, cursorPos);
}

View File

@@ -379,7 +379,7 @@ void Terminal::ExpandSelectionToWord()
_selection->pivot = _selection->start;
_selection->end = buffer.GetWordEnd(_selection->end, _wordDelimiters);
// if we're targetting both endpoints, instead just target "end"
// if we're targeting both endpoints, instead just target "end"
if (WI_IsFlagSet(_selectionEndpoint, SelectionEndpoint::Start) && WI_IsFlagSet(_selectionEndpoint, SelectionEndpoint::End))
{
_selectionEndpoint = SelectionEndpoint::End;

View File

@@ -10,4 +10,5 @@
#include "winrt/Windows.Foundation.h"
#include "winrt/Microsoft.Terminal.Core.h"
#include <til.h>

View File

@@ -15,6 +15,7 @@
<ClInclude Include="..\ControlKeyStates.hpp" />
<ClInclude Include="..\pch.h" />
<ClInclude Include="..\Terminal.hpp" />
<ClInclude Include="..\tracing.hpp" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,19 @@
/*++
Copyright (c) Microsoft Corporation
Licensed under the MIT license.
Module Name:
- tracing.hpp
Abstract:
- This module is used for recording tracing/debugging information to the telemetry ETW channel
--*/
#pragma once
#include <string>
#include <windows.h>
#include <winmeta.h>
#include <TraceLoggingProvider.h>
#include <telemetry/ProjectTelemetry.h>
TRACELOGGING_DECLARE_PROVIDER(g_hCTerminalCoreProvider);

View File

@@ -91,6 +91,17 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
InitializeComponent();
{
using namespace winrt::Windows::Globalization::NumberFormatting;
// > .NET rounds to 12 significant digits when displaying doubles, so we will [...]
// ...obviously not do that, because this is an UI element for humans. This prevents
// issues when displaying 32-bit floats, because WinUI is unaware about their existence.
SignificantDigitsNumberRounder rounder;
rounder.SignificantDigits(6);
// BODGY: Depends on WinUI internals.
_fontSizeBox().NumberFormatter().as<DecimalFormatter>().NumberRounder(rounder);
}
INITIALIZE_BINDABLE_ENUM_SETTING(CursorShape, CursorStyle, winrt::Microsoft::Terminal::Core::CursorStyle, L"Profile_CursorShape", L"Content");
INITIALIZE_BINDABLE_ENUM_SETTING(AdjustIndistinguishableColors, AdjustIndistinguishableColors, winrt::Microsoft::Terminal::Core::AdjustTextMode, L"Profile_AdjustIndistinguishableColors", L"Content");
INITIALIZE_BINDABLE_ENUM_SETTING_REVERSE_ORDER(BackgroundImageStretchMode, BackgroundImageStretchMode, winrt::Windows::UI::Xaml::Media::Stretch, L"Profile_BackgroundImageStretchMode", L"Content");

View File

@@ -34,7 +34,7 @@ namespace Microsoft.Terminal.Settings.Editor
IHostedInWindow WindowRoot; // necessary to send the right HWND into the file picker dialogs.
OBSERVABLE_PROJECTED_APPEARANCE_SETTING(String, FontFace);
OBSERVABLE_PROJECTED_APPEARANCE_SETTING(Int32, FontSize);
OBSERVABLE_PROJECTED_APPEARANCE_SETTING(Single, FontSize);
OBSERVABLE_PROJECTED_APPEARANCE_SETTING(Windows.UI.Text.FontWeight, FontWeight);
OBSERVABLE_PROJECTED_APPEARANCE_SETTING(String, ColorSchemeName);

View File

@@ -93,7 +93,8 @@
HasSettingValue="{x:Bind Appearance.HasFontSize, Mode=OneWay}"
SettingOverrideSource="{x:Bind Appearance.FontSizeOverrideSource, Mode=OneWay}"
Visibility="{x:Bind Appearance.IsDefault, Mode=OneWay}">
<muxc:NumberBox x:Uid="Profile_FontSizeBox"
<muxc:NumberBox x:Name="_fontSizeBox"
x:Uid="Profile_FontSizeBox"
AcceptsExpression="False"
LargeChange="10"
Maximum="128"

View File

@@ -20,8 +20,8 @@
<DataTemplate x:Key="ColorPreviewChipTemplate"
x:DataType="local:ColorTableEntry">
<Border Width="15"
Height="15"
<Border Width="12"
Height="12"
Background="{x:Bind local:Converters.ColorToBrush(Color)}"
CornerRadius="2" />
</DataTemplate>
@@ -40,7 +40,6 @@
<StackPanel Style="{StaticResource SettingsStackStyle}">
<TextBlock x:Uid="ColorSchemesDisclaimer"
Style="{StaticResource DisclaimerStyle}" />
<ListView x:Name="ColorSchemeListView"
MaxWidth="{StaticResource StandardControlMaxWidth}"
ItemsSource="{x:Bind ViewModel.AllColorSchemes, Mode=OneWay}"
@@ -55,31 +54,17 @@
Style="{StaticResource SchemeGridStyle}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0"
VerticalAlignment="Center"
Style="{StaticResource SettingsPageItemHeaderStyle}"
Text="{x:Bind Name, Mode=OneWay}" />
<Border Grid.Column="1"
Margin="10,0,0,0"
Padding="2,0,2,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Background="{ThemeResource SystemAltMediumLowColor}"
BorderBrush="{ThemeResource SystemControlForegroundBaseMediumBrush}"
BorderThickness="1"
CornerRadius="1"
Visibility="{x:Bind IsDefaultScheme, Mode=OneWay}">
<TextBlock x:Uid="ColorScheme_DefaultTag"
Grid.Column="1"
Foreground="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
</Border>
<Grid Grid.Column="2"
<!-- Set the height of the inner grid as 48 to be 3/4 of the ListViewItem height -->
<Grid Grid.Column="0"
Height="48"
Padding="12,11,8,8"
VerticalAlignment="Center"
ColumnSpacing="4"
RowSpacing="4">
Background="{x:Bind local:Converters.ColorToBrush(BackgroundColor.Color), Mode=OneWay}"
ColumnSpacing="2"
CornerRadius="4"
RowSpacing="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
@@ -95,99 +80,110 @@
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Border Grid.RowSpan="2"
Grid.Column="0"
Background="{x:Bind local:Converters.ColorToBrush(BackgroundColor.Color), Mode=OneWay}"
CornerRadius="2">
<TextBlock Padding="10,0,10,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
AutomationProperties.AccessibilityView="Raw"
FontFamily="Cascadia Code"
Foreground="{x:Bind local:Converters.ColorToBrush(ForegroundColor.Color), Mode=OneWay}"
Text="AaBbCc" />
</Border>
<ContentControl Grid.Row="0"
Grid.Column="1"
Grid.Column="0"
Content="{x:Bind ColorEntryAt(0), Mode=OneWay}"
ContentTemplate="{StaticResource ColorPreviewChipTemplate}"
IsTabStop="False" />
<ContentControl Grid.Row="0"
Grid.Column="2"
Grid.Column="1"
Content="{x:Bind ColorEntryAt(1), Mode=OneWay}"
ContentTemplate="{StaticResource ColorPreviewChipTemplate}"
IsTabStop="False" />
<ContentControl Grid.Row="0"
Grid.Column="3"
Grid.Column="2"
Content="{x:Bind ColorEntryAt(2), Mode=OneWay}"
ContentTemplate="{StaticResource ColorPreviewChipTemplate}"
IsTabStop="False" />
<ContentControl Grid.Row="0"
Grid.Column="4"
Grid.Column="3"
Content="{x:Bind ColorEntryAt(3), Mode=OneWay}"
ContentTemplate="{StaticResource ColorPreviewChipTemplate}"
IsTabStop="False" />
<ContentControl Grid.Row="0"
Grid.Column="5"
Grid.Column="4"
Content="{x:Bind ColorEntryAt(4), Mode=OneWay}"
ContentTemplate="{StaticResource ColorPreviewChipTemplate}"
IsTabStop="False" />
<ContentControl Grid.Row="0"
Grid.Column="6"
Grid.Column="5"
Content="{x:Bind ColorEntryAt(5), Mode=OneWay}"
ContentTemplate="{StaticResource ColorPreviewChipTemplate}"
IsTabStop="False" />
<ContentControl Grid.Row="0"
Grid.Column="7"
Grid.Column="6"
Content="{x:Bind ColorEntryAt(6), Mode=OneWay}"
ContentTemplate="{StaticResource ColorPreviewChipTemplate}"
IsTabStop="False" />
<ContentControl Grid.Row="0"
Grid.Column="8"
Grid.Column="7"
Content="{x:Bind ColorEntryAt(7), Mode=OneWay}"
ContentTemplate="{StaticResource ColorPreviewChipTemplate}"
IsTabStop="False" />
<ContentControl Grid.Row="1"
Grid.Column="1"
Grid.Column="0"
Content="{x:Bind ColorEntryAt(8), Mode=OneWay}"
ContentTemplate="{StaticResource ColorPreviewChipTemplate}"
IsTabStop="False" />
<ContentControl Grid.Row="1"
Grid.Column="2"
Grid.Column="1"
Content="{x:Bind ColorEntryAt(9), Mode=OneWay}"
ContentTemplate="{StaticResource ColorPreviewChipTemplate}"
IsTabStop="False" />
<ContentControl Grid.Row="1"
Grid.Column="3"
Grid.Column="2"
Content="{x:Bind ColorEntryAt(10), Mode=OneWay}"
ContentTemplate="{StaticResource ColorPreviewChipTemplate}"
IsTabStop="False" />
<ContentControl Grid.Row="1"
Grid.Column="4"
Grid.Column="3"
Content="{x:Bind ColorEntryAt(11), Mode=OneWay}"
ContentTemplate="{StaticResource ColorPreviewChipTemplate}"
IsTabStop="False" />
<ContentControl Grid.Row="1"
Grid.Column="5"
Grid.Column="4"
Content="{x:Bind ColorEntryAt(12), Mode=OneWay}"
ContentTemplate="{StaticResource ColorPreviewChipTemplate}"
IsTabStop="False" />
<ContentControl Grid.Row="1"
Grid.Column="6"
Grid.Column="5"
Content="{x:Bind ColorEntryAt(13), Mode=OneWay}"
ContentTemplate="{StaticResource ColorPreviewChipTemplate}"
IsTabStop="False" />
<ContentControl Grid.Row="1"
Grid.Column="7"
Grid.Column="6"
Content="{x:Bind ColorEntryAt(14), Mode=OneWay}"
ContentTemplate="{StaticResource ColorPreviewChipTemplate}"
IsTabStop="False" />
<ContentControl Grid.Row="1"
Grid.Column="8"
Grid.Column="7"
Content="{x:Bind ColorEntryAt(15), Mode=OneWay}"
ContentTemplate="{StaticResource ColorPreviewChipTemplate}"
IsTabStop="False" />
<TextBlock Grid.RowSpan="2"
Grid.Column="8"
Padding="10,0,10,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
AutomationProperties.AccessibilityView="Raw"
FontFamily="Cascadia Code"
Foreground="{x:Bind local:Converters.ColorToBrush(ForegroundColor.Color), Mode=OneWay}"
Text="{x:Bind Name, Mode=OneWay}" />
</Grid>
<Border Grid.Column="1"
Margin="10,0,0,0"
Padding="2,0,2,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Background="{ThemeResource SystemAltMediumLowColor}"
BorderBrush="{ThemeResource SystemControlForegroundBaseMediumBrush}"
BorderThickness="1"
CornerRadius="1"
Visibility="{x:Bind IsDefaultScheme, Mode=OneWay}">
<TextBlock x:Uid="ColorScheme_DefaultTag"
Grid.Column="1"
Foreground="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
</Border>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>

View File

@@ -88,6 +88,11 @@
<ToggleSwitch IsOn="{x:Bind ViewModel.DetectURLs, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<local:SettingContainer x:Uid="Globals_ConfirmCloseAllTabs">
<ToggleSwitch IsOn="{x:Bind ViewModel.ConfirmCloseAllTabs, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
</StackPanel>
</ScrollViewer>
</Page>

View File

@@ -27,6 +27,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_GlobalSettings, FocusFollowMouse);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_GlobalSettings, DetectURLs);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_GlobalSettings, WordDelimiters);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_GlobalSettings, ConfirmCloseAllTabs);
private:
Model::GlobalAppSettings _GlobalSettings;

View File

@@ -24,5 +24,6 @@ namespace Microsoft.Terminal.Settings.Editor
PERMANENT_OBSERVABLE_PROJECTED_SETTING(Boolean, FocusFollowMouse);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(Boolean, DetectURLs);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(String, WordDelimiters);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(Boolean, ConfirmCloseAllTabs);
}
}

View File

@@ -532,7 +532,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
if (!profile.Deleted())
{
auto navItem = _CreateProfileNavViewItem(_viewModelForProfile(profile, _settingsClone));
Controls::ToolTipService::SetToolTip(navItem, box_value(profile.Name()));
menuItems.Append(navItem);
}
}
@@ -540,7 +539,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
// Top off (the end of the nav view) with the Add Profile item
MUX::Controls::NavigationViewItem addProfileItem;
addProfileItem.Content(box_value(RS_(L"Nav_AddNewProfile/Content")));
Controls::ToolTipService::SetToolTip(addProfileItem, box_value(RS_(L"Nav_AddNewProfile/Content")));
addProfileItem.Tag(box_value(addProfileTag));
FontIcon icon;

View File

@@ -16,6 +16,8 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
_Label{ label },
_SubPage{ subPage } {}
hstring ToString() { return _Label; }
WINRT_PROPERTY(IInspectable, Tag);
WINRT_PROPERTY(winrt::hstring, Label);
WINRT_PROPERTY(BreadcrumbSubPage, SubPage);

View File

@@ -21,7 +21,7 @@ namespace Microsoft.Terminal.Settings.Editor
ColorSchemes_Edit
};
runtimeclass Breadcrumb
runtimeclass Breadcrumb : Windows.Foundation.IStringable
{
IInspectable Tag;
String Label;

View File

@@ -51,22 +51,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
// NOTE: this is similar to what is done with BackgroundImagePath above
_NotifyChanges(L"UseParentProcessDirectory", L"UseCustomStartingDirectory");
}
else if (viewModelProperty == L"UseAcrylic")
{
// GH#11372: If we're on Windows 10, and someone turns off
// acrylic, we're going to disable opacity for them. Opacity
// doesn't work without acrylic on Windows 10.
//
// BODGY: CascadiaSettings's function IsDefaultTerminalAvailable
// is basically a "are we on Windows 11" check, because defterm
// only works on Win11. So we'll use that.
//
// Remove when we can remove the rest of GH#11285
if (!UseAcrylic() && !CascadiaSettings::IsDefaultTerminalAvailable())
{
Opacity(1.0);
}
}
else if (viewModelProperty == L"AntialiasingMode")
{
_NotifyChanges(L"CurrentAntiAliasingMode");

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