Compare commits

..

73 Commits

Author SHA1 Message Date
Dustin L. Howett
b47e924565 Migrate spelling-0.0.21 changes from main 2021-05-24 08:33:20 -05:00
Dustin L. Howett
34ecd1757f Migrate spelling-0.0.19 changes from main 2021-05-24 08:33:20 -05:00
Dustin L. Howett
93004173ec Emit fixup debug info for internal tooling (#10151)
See MSFT-33187224 for more information.

This may impact debuggability; I have no idea how to tell.

(cherry picked from commit 89af44488f)
2021-05-24 11:49:34 -05:00
Don-Vito
458a140ad7 Fix overflow in scroll-to-bottom (#9389)
## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/issues/9353
* [x] CLA signed.
* [ ] Tests added/passed
* [ ] Documentation updated.
* [ ] Schema updated.
* [ ] I've discussed this with core contributors already.

(cherry picked from commit 1202f89399)
2021-03-15 18:28:46 -05:00
Carlos Zamora
cd68bd0dfd Change SettingsTab close icon to be smaller (#9324)
We were using the wrong close icon for the settings tab. This is a side effect of `TerminalTab` overriding `TabBase`'s implementation.

#6800 - Settings UI Epic

Closes #9317

(cherry picked from commit 4a95341caf)
2021-03-15 18:28:45 -05:00
Eric Tian
c8be59f4a9 Display correct tooltip when window is maximized (#9412)
## Summary of the Pull Request
Instead of displaying "Maximize" in the tooltip for the maximize/restore button even when the window is maximized, it now displays "Restore Down".

## References
Fixes #5693

## PR Checklist
* [X] Closes #5693
* [X] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [X] Tests added/passed

## Validation Steps Performed
Tested manually.

(cherry picked from commit 8358f8d93f)
2021-03-15 18:25:14 -05:00
Don-Vito
0026b67dd6 Invalidate nested command with no valid subcommands (#9495)
Currently, when loading command with sub-commands that fail to parse,
we result with command that:
* Is not considered nested (has no sub-commands)
* Has no action of its own

The commit contains a few changes:
1. Protection in the dispatch that will prevent NPE
2. Change in the command parsing that will no load
a command if all its sub-commands failed to parse
3. We will add a warning in this case (the solution is somewhat
hacky, due to the hack that was there previously)

When such command is passed to a dispatch we crash with NPE.

Closes #9448

(cherry picked from commit 28da6c4ecb)
2021-03-15 18:25:03 -05:00
Don-Vito
00f4382d63 Fix selection on multi-click with no shift (#9455)
When working on #9403 I completely forgot that
double-click and triple-click should work even without shift.
Fixed it by allowing multi-selection even if not shift is pressed.

Closes #9453

## Validation Steps Performed
* [x] single click = no selection
* [x] single click and drag = selection starting from first point
* [x] single click in unfocused pane and drag = focus pane, selection starting from first point
* [x] double-click = selects a whole word
* [x] triple-click = selects a whole line
* [x] double-click and drag = selects a whole word, drag selects whole words
* [x] triple-click and drag = selects a whole line, drag selects whole lines
* [x] Shift single-click = defines start point
* [x] second Shift single-click = defines end point
* [x] Shift double-click = selects entire word
* [x] Shift triple-click = selects entire line
* [x] Shift double-click and drag = selects entire word, drag selects whole words
* [x] Mouse mode: Shift single-click = defines start point
* [x] Mouse mode: second Shift single-click = defines end point
* [x] Mouse mode: Shift double-click = selects entire word
* [x] Mouse mode: Shift triple-click = selects entire line
* [x] Mouse mode: Shift double-click and drag = selects entire word, drag selects whole words

(cherry picked from commit efc92de19f)
2021-03-15 18:23:42 -05:00
Don-Vito
57f727c01f Allow interaction with hyperlinks in mouse mode (#9396)
## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/issues/9117
* [x] CLA signed.
* [x] Tests added/passed
* [ ] Documentation updated.
* [ ] Schema updated.
* [x] I've discussed this with core contributors already.

## Detailed Description of the Pull Request / Additional comments
In mouse mode:
* Underline hyperlinks
* Activate hyperlink on ctrl+click rather than sending input to VT

(cherry picked from commit 6cd4e03a58)
2021-03-15 18:23:41 -05:00
Dustin L. Howett
daa8c44505 Update C++/WinRT to 2.0.210309.3 (#9437)
This update shrinks our binaries a little bit.

From a representative build on VS 16.8:

       | App     | Control | Connection | TSE     | WT     | Total   | msix (zip) |
       | --      | --      | --         | --      | --     | --      | --         |
Before | 2610176 | 1006592 | 433152     | 1352192 | 321536 | 5723648 | 8336910    |
After  | 2532352 | 986624  | 431104     | 1312768 | 313344 | 5576192 | 8287648    |
Delta  | 77824   | 19968   | 2048       | 39424   | 8192   | 147456  | 49262      |
%Delta | 2.98%   | 1.98%   | 0.47%      | 2.92%   | 2.55%  | 2.58%   | 0.59%      |

(cherry picked from commit 3029bb8a68)
2021-03-15 18:23:37 -05:00
Don-Vito
763dab5d7f Fix selection logic with shift on multi-click (#9403)
## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/issues/9382
* [x] CLA signed.
* [ ] Tests added/passed
* [ ] Documentation updated.
* [ ] Schema updated.
* [ ] I've discussed this with core contributors already.

## Detailed Description of the Pull Request / Additional comments
The selection with shift is quite broken in 1.6.

It started with #8611 that introduces cell selection on `shift+click`.
This change resulted in the following defect:
`shift+double-click`, `shift+triple-click` select only parts  of the word.
The reason for this is that the first `shift+click` establishes the selection,
while the consequent clicks simply extend it to the relevant boundary
(aka word / line boundary)

However, the logic was broken even before #8611.
For instance, `shift+triple-click` had exactly the same handicap:
`shift+double-click` was establishing the selection and the
third click was simply extending it to the line boundary.

This PR addresses the both defects in the following manner:
upon multi-click that starts new selection we establish
a new selection on every consequent click using appropriate mode
(cell/word/line) rather than trying to extend one.
For this purpose we remember the position that started the selection.

(cherry picked from commit 83f2a3bb3d)
2021-03-15 18:23:33 -05:00
Don-Vito
86fa001dd6 Fix TermControl initialization to pre-seed working dir (#9397)
## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/issues/8969
* [x] CLA signed.
* [ ] Tests added/passed
* [ ] Documentation updated.
* [ ] Schema updated.
* [ ] I've discussed this with core contributors already.

<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments

<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed

(cherry picked from commit 19bd0c94e7)
2021-03-15 18:23:32 -05:00
Dustin L. Howett
507a84664e Update Cascadia Code to 2102.25 (#9295)
This update fixes some issues in Cascadia Code's February update:

microsoft/cascadia-code#406 - updated anchor type to lock with the other equals-related ligatures
microsoft/cascadia-code#408 - corrected component used for glyph to align with Unicode
microsoft/cascadia-code#412 - updated locl features removing iacute_j ligature and Catalan substitution
microsoft/cascadia-code#414 - increased overlaps of middle glyph for arrow ligatures
microsoft/cascadia-code#415 - reduces width of macronbelow
microsoft/cascadia-code#416 - rolls back name ID 4 modification as JetBrains cannot process it correctly
microsoft/cascadia-code#428 - rolls back variation of the underline to prevent MVAR table generation

Full changelist:
* Repositioned tilde in related ligatures. Previously it was higher than the standard one.
* Added missing vietnamese anchors on acute and grave (futureproofing).
* Corrected / made consistent greater & less positioning in </> and <$> related ligatures.
* Otherwise reviewed hinting

(cherry picked from commit cb03b97e67)
2021-02-25 14:48:02 -08:00
Dustin L. Howett
35a9314aa5 Exclude MonarchPeasantPackage from AnyCPU/DotNet*Test configs (#9272)
Visual Studio automatically enabled this package to build in all
configurations. This results in a build error when we go to pack the WPF
control.

(cherry picked from commit 66033dcb01)
2021-02-24 11:34:43 -08:00
Dustin L. Howett
68887fc94e Hide the Command Palette's key binding label from UIA (#9234)
The command palette's list items explicitly specify the "AcceleratorKey"
property (for UIA) and set it to the key binding. Putting it in a label
inside the list item makes Narrator read it out twice ("New Tab ...
ctrl+shift+t ... ctrl+shift+t").

Addresses #7913 (to be closed when a11y re-evaluates)

(cherry picked from commit c9dea60bbe)
2021-02-24 11:24:36 -08:00
Carlos Zamora
83d35c1191 [v1.6] Add help text to 'more options' in command palette (#9262)
This adds help text (automation property) to command palette commands that expand to more options.

Addresses #7908

## Validation Steps Performed
If I have a nested command called "color tab", NVDA reads it as...
"Color tab. More options. 5 of 79."
2021-02-23 18:56:00 -08:00
Don-Vito
b54429823e Re-enable navigation in ATS (#9140)
## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/issues/9130
* [x] CLA signed.
* [ ] Tests added/passed
* [ ] Documentation updated.
* [ ] Schema updated.
* [ ] I've discussed this with core contributors already.

(cherry picked from commit 5ffb945b66)
2021-02-23 15:57:07 -08:00
Ben Constable
d7fcc56b90 Add Keyboard Navigation To Color Picker (#9144)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request

Add the keyboard navigation to the color picker.
Test manually.

<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References

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

<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments

<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed

Tested manually

(cherry picked from commit ca226d62e2)
2021-02-23 15:56:06 -08:00
Dustin L. Howett
b6927b24e8 Remove accidental System.Core.dll from CascadiaPackage (#9153)
A bug in VS 16.8 makes the WAP packaging project copy System.Core.dll
from the CLR into all WAP packages. We don't need it, and it adds 300kb
to our package (670kb uncompressed).

VS 16.9 sets the AddAdditionalExplicitAssemblyReferences to suppress
this assembly. If we do the same, we can avoid the reference *and* be
eady for VS 16.9.

(cherry picked from commit c1f844307c)
2021-02-23 15:55:47 -08:00
Don-Vito
d33dd1ffce Teach tab to focus terminal after rename (#9162)
## Summary of the Pull Request
After rename ends (either by enter or escape) the rename box
gets collapsed and the focus moves to the next tab stop
in the TabView (e.g., new tab button).

To overcome this:
* Added RenameEnded event to TabHeaderControl
* Forwarded it as RenamerDeactivated from TerminalTab
* Registered in the TerminalPage to focus the active control upon
RenamerDeactivated if focus didn't move to tab menu.

This means, no matter how you close the renamer,
the current terminal gains the focus.

## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/issues/9160
* [x] CLA signed.
* [ ] Tests added/passed
* [ ] Documentation updated.
* [ ] Schema updated.
* [ ] I've discussed this with core contributors already.

(cherry picked from commit 00d1dc99e4)
2021-02-23 15:55:10 -08:00
PankajBhojwani
da5ec7b2a2 Always show the bell indicator when BEL is emitted (#9212)
Regardless of whether the bellstyle is set to visual,
show the bell indicator in the tab header

(cherry picked from commit d12a71cdf9)
2021-02-23 15:54:37 -08:00
Dustin Howett
ba534aaad6 [STABLE ONLY] Combined revert of Environment Block Changes
Revert "Fix environment block creation (#7401)"

This reverts commit 7886f16714.

(cherry picked from commit e46ba65665)

Revert "Always create a new environment block before we spawn a process (#7243)"

This reverts commit 849243af99.

References #7418

(cherry picked from commit 4204d2535c)
2021-02-23 15:54:17 -08:00
Carlos Zamora
7541b71de8 Fix command palette accessibility (#9143)
Fixes a regression of command palette accessibility. The regression was
introduced in #8377 by setting `IsTabStop` to false. Though the commands
would light up, the focus didn't technically get on the command, so the
screen reader would just read the text box.

Opened the command palette while NVDA is active. It now reads the
commands as focus moves on them.

(cherry picked from commit ac3e4bfe56)
2021-02-23 15:54:17 -08:00
Carlos Zamora
ac9d3dcfbe Update automation properties for tab header control (#9258)
This sets the automation property (name) on the tab view item we expose in XAML.

## PR Checklist
* [x] Closes #9254

## Validation Steps Performed
Tested under NVDA and Accessibility Insights

(cherry picked from commit ef4f2ca03e)
2021-02-23 15:54:16 -08:00
Dustin L. Howett
f7b205fa78 TabHeader: put TraceLogging events in the right category (#9257)
Fixes MSFT-31615100

(cherry picked from commit 17c6f8e9ff)
2021-02-23 15:54:16 -08:00
Don-Vito
ff126c5a2f Ensure hyperlinks de-underline when pointer leaves terminal (#9195)
Introduced PointerExited handler to nullify last hovered cell
(which will also de-underline the hyperlink if required).

Closes #9141

(cherry picked from commit 52d1533c4f)
2021-02-23 15:54:16 -08:00
SJ
91f68e2914 Do not dismiss selection if the Windows keys is pressed as a key-combination (#9163)
Aims to fix #8791.

<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Prior to this PR, if the Windows key was pressed as a part of a key combination, then selection was being dismissed. For example,  when a user pressed `Windows` + `Shift` + `S` keys to invoke the _Capture & Annotate_ tool.
This PR adds an exception for not clearing selection when either of the two Windows keys are pressed as part of a key combination.
It was tested manually by trying to reproduce the issue.

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [ ] Closes #8791
* [x ] CLA signed.
* [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: #8791

<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
1. Build Terminal.
2. Write anything & make a selection.
3. Press `Windows`+ `Shift` + `S` keys.
4. The _Capture & Annotate_ tool appears but the selection made in step 2 isn't dismissed (doesn't disappear).

(cherry picked from commit 7d37ba22e7)
2021-02-23 15:54:16 -08:00
Carlos Zamora
245a244f1b [v1.6 ONLY] Make Settings UI inaccessible (#9225) 2021-02-22 10:31:23 -08:00
Javier
fc57c82f80 wpf: prevent a 0 size when VS builds the Terminal window too early (#9194)
The terminal WPF container might have a (0,0) render size when VS
eagerly attempts to initialize the terminal tool window when it is
pinned during startup, but no actual UI is shown due to the VS welcome
dialog that shows up before VS can build the terminal tool window.

We've fixed this issue previously in other areas but only recently did
we get a complete enough dump to find the corner cases for this issue.

This should patch all the gaps that cause this bug.

## Validation Steps Performed
I've manually validated the scenarios shown in the user dumps.

(cherry picked from commit 12eb69f665)
2021-02-17 13:06:19 -08:00
Carlos Zamora
c24194a3f3 Bugfix: update color scheme references properly (#9103)
`CascadiaSettings::UpdateColorSchemeReferences` had two bugs in it:
1. we would never check/update the base layer
2. we would explicitly set the color scheme on a profile referencing the
   old name

This PR fixes both of those issues by checking/updating the base layer,
and ensuring that we check if a profile has an explicit reference before
updating it.

Since the affected code is in TSM, I also created an automated local
test.

## Validation Steps Performed
Bug repro steps.
Specifically tested [DHowett's scenario] too.
Test added.

Closes #9094

[DHowett's scenario]: https://github.com/microsoft/terminal/issues/9094#issuecomment-776412781

(cherry picked from commit 42511265e5)
2021-02-10 14:12:26 -08:00
Don-Vito
3ab1d724d2 Fix CommandPalette to prefer inner interactions over bindings (#9056)
* Currently TerminalPage registers on CmdPal key events:
  * To invoke bindings when the palette is open
  * Since some key combinations are not triggered by KeyDown
    it registers for PreviewKeyDown
* As a result bindings might be preferred over navigation
  (e.g., ctrl+v will paste into Terminal rather than into search box)
* To fix this, I moved all interactions inside the CmdPal into
  PreviewKeyDown as well
* In addition, added specific handling for copy/paste
  which now allow to interact with search box even if not focused

Closes #9044

(cherry picked from commit ed19301ad3)
2021-02-10 12:37:21 -08:00
Dustin L. Howett
e13d1a7b61 [1.5 ONLY] Remove the close submenu (#9102)
There's a platform issue that causes it to crash.
Fixes #8944.

(cherry picked from commit 5fdd1560fd)
2021-02-10 11:55:49 -08:00
Michael Niksa
48543bb3e7 Teach the renderer to keep thread alive if engine requests it (#9091)
Teaches renderer base to keep thread alive if engine requests it.
`DxEngine` now requests it if shaders are on.

- The render engine interface now has a true/false to return whether the
  specific renderer wants another frame to immediately follow up. The
  renderer base will ask for this information as it ends the paint on
  any particular engine (which is the time where invalid regions are
  typically cleaned up) and just poke the render thread the same as if
  an invalidation request came in from outside of render-land. That will
  trigger the render thread to just keep moving in the same way as any
  other invalidation.

## Validation Steps Performed
- [x] Actually built it
- [x] Actually try it

I promised this in #8994

(cherry picked from commit 3b247812ce)
2021-02-10 11:26:06 -08:00
Dustin L. Howett
91b867102c Work around a (likely) optimizer issue with SetPixelShaderPath (#9092)
It appears as though the optimizer is generating a sequence of
instructions on x64 that results in a nonsense std::wstring_view being
passed to SetPixelShaderPath when it's converted from a winrt::hstring.

Initially, I suspected that the issue was in us caching `_settings`
before we broke off the coroutine to update settings on the UI thread. I
implemented a quick fix for this (applying values off the new settings
object while also storing it in the control instance), but it didn't
actually lead anywhere. I do think it's the right thing to do for code
health's sake. Pankaj already changed how this works in 1.7: we no
longer (ever) re-seat the `_settings` reference... we only ever change
its parentage. Whether this is right or wrong is not for this paragraph
to discuss.

Eventually, I started looking more closely at the time travel traces. It
seriously looks like the wstring_view is generated wrong to begin with.
The debugger points directly at `return { L"", 0 };` (which is correct),
but the values we get immediately on the other side of the call are
something like `{ 0x7FFFFFFF, 0 }` or `{ 0x0, 0x48454C4C }`.

I moved _just_ the call to SetPixelShaderPath into a separate function.
The bug miraculously disappeared when I marked it **noinline**. It
reappeared when the function was fully inlined.

To avoid any future issues, I moved the whole UI thread body of
UpdateSettings out into its own function, to be called only while on the
UI thread. This fixes the bug.

Closes #8723.
Closes #9064.

## Validation Steps Performed

I found a repro (update the settings file every 0.5 seconds and resize
the terminal wildly while it's doing so) that would trigger the bug
within ~10 seconds. It stopped doing so.
2021-02-10 11:25:55 -08:00
Don-Vito
4014100b2d Prevent command palette from closing on right click (#9057)
The command palette is ephemeral and is dismissed if the focus
moves to an element which is not the palette's descendant.

Unfortunately, this breaks the (right-click) context menu,
as it  is not a child of the palette
(popups are hosted on a separate root element).

(cherry picked from commit 5f8e3d1676)
2021-02-09 11:45:59 -08:00
Sarim Khan
3778924aa4 fix tab title propagation issues (#9054)
- Fixes empty app title when  `showTerminalTitleInTitlebar` is false
- Fixes Tab title propagation to Window title when
  `showTerminalTitleInTitlebar` is false
- Fixes Tab title propagation to Window - title doesn't update when
  Window is unfocused

1. There were a missing
   `_settings.GlobalSettings().ShowTitleInTitlebar()` check. Because of
   this Title update event was being fired even when
   `showTerminalTitleInTitlebar` is false. This results in empty tab
   title to propagate to Window title. Also then after switching tabs
   back and forth, tab title propagates to window title. These shouldn't
   propagate when `showTerminalTitleInTitlebar` is false. I added the
   `showTerminalTitleInTitlebar` check in relevant logic to fix the
   behavior.

2. Code was checking `tab.FocusState() != FocusState::Unfocused` , but
   when the whole terminal window is not in focus, the active tab is
   also in Unfocused state. This was preventing tab title to propagate
   to window title when application is unfocused. I added the logic of
   checking matching selected tabs' index. This fixes the issue.

## Validation Steps Performed
I did the reproduce steps descripted in the issue to reproduce the bugs.
After applying the fixes, the bugs don't appear anymore while doing the
reproduce steps.

Closes #8704

(cherry picked from commit 47881a802f)
2021-02-09 11:45:15 -08:00
Dustin L. Howett
c01573b5d3 Update Cascadia Code to 2102.03 (#9088)
The February 2021 update of Cascadia Code fixes 23 issues and
introduces support for infinite arrow ligatures and control pictures.

(cherry picked from commit 6af49a5246)
2021-02-09 11:44:43 -08:00
PankajBhojwani
62a12eeb79 Fix crash when closing multiple splits from the tab context menu (#9028)
## Summary of the Pull Request
Fix for #9021

Turns out that what was happening is that the _parent_ pane's `Closed` event was being caught by the tab, and parent panes always have `nullopt` as their id. So now the `Pane::Id()` call always returns an optional, allowing us to check if it has a value before we access it.

## PR Checklist
* [x] Closes #9021

## Validation Steps Performed
No more crash

(cherry picked from commit ed4e829adc)
2021-02-04 16:55:53 -08:00
Lachlan Picking
e457a1a868 Fix shader time input (#8994)
Correctly sets the time input on the pixelShaderSettings struct, which was previously hard-coded to `0.0f`.

## PR Checklist
* [x] Closes #8935
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [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: #8935

## Detailed Description of the Pull Request / Additional comments
I added a private field to `DxEngine` to store the timestamp for when a custom shader is first loaded. The field is initialized in `_SetupTerminalEffects()`, and the calculated time value (seconds since the timestamp) passed to the actual shader is set in `_ComputePixelShaderSettings()`.

There remains an issue with with jerky animation due to the renderer not repainting when the window contents are not updated (see discussion in the original issue).

This is basically my first time writing C++; constructive review is enthusiastically welcomed 🙂

## Validation Steps Performed
I manually tested using a variety of simple shaders that rely on time input for animation.

(cherry picked from commit 9fb4fb2741)
2021-02-04 16:55:16 -08:00
Don-Vito
1c0bbe72d3 Prevent context menu of tab renamer text box from canceling edit (#8979)
## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/issues/8975
* [x] CLA signed.
* [ ] Tests added/passed
* [ ] Documentation updated.
* [ ] Schema updated.
* [ ] I've discussed this with core contributors already.

## Detailed Description of the Pull Request / Additional comments
* We dismiss the edit each time `HeaderRenamerTextBox` loses focus
* Unfortunately, this applies also to scenario where the context menu
(copy, paste, select, etc.) is open with the right-click
* The fix is to ignore focus loss if `HeaderRenamerTextBox().ContextFlyout()` is open.
* We can do it as upon the fly-out dismiss the text box regains the focus.

![RenamerContextMenu](https://user-images.githubusercontent.com/4639110/106394866-90b10100-6407-11eb-8e92-627be4f70500.gif)

(cherry picked from commit 636f436465)
2021-02-04 16:54:53 -08:00
Don-Vito
cf694747a0 Fix cursor restore to happen on the tab row (#8952)
Closes #8918

(cherry picked from commit 9cb8db8e9a)
2021-02-04 16:47:56 -08:00
Carlos Zamora
9444617bc6 Serialize 'disabledProfileSources' (#9038)
"disabledProfileSources" is saved to `CascadiaSettings` _not_
`GlobalAppSettings` (and, even then, it's only read when it's used,
never saved). This PR specifically detects if it was defined in
settings.json, and copies it over when the settings are serialized.

## Validation Steps Performed
1. Added "disabledProfileSources" to settings.json, then serialized. -->
   "disabledProfileSources" is now maintained.
2. Updated `CascadiaSettings` serialization test

Closes #9032

(cherry picked from commit 230fad533e)
2021-02-04 16:47:55 -08:00
Don-Vito
b80f6de58c Fix hyperlink not de-underlined in unfocused pane (#9039)
Ensures that:
* All hyperlink related logic is running on unfocused pane
* All unrelated logic is not running on unfocused pane

Closes #8925

(cherry picked from commit 40e328984d)
2021-02-04 16:47:55 -08:00
Chester Liu
34bb1cbd01 Improve OSC 9;9 parsing logic & add tests (#8934)
This PR fixes the parsing of OSC 9;9 sequences with path surrounded by
quotation marks.

Original OSC 9;9 PR: #8330

Unit test added. Manually tested with oh-my-posh.

Closes #8930

(cherry picked from commit 0811c572ae)
2021-02-04 16:47:55 -08:00
Carlos Zamora
b656fdd34f Generate settings.json if deleted while WT is open (#9012)
The settings.json was not regenerated if WT was already open. This resulted in the `ShellExecute` from trying to open the settings to pop up Notepad and say that this file didn't exist. We now detect if the settings.json was deleted to kick off loading the settings.

Closes #8955

(cherry picked from commit a5931fbead)
2021-02-04 16:47:55 -08:00
Mike Griese
41e9c59879 Manually initialize the warnings vector to prevent a crash on launch (#8995)
## Summary of the Pull Request

Oops, winrt `IVector`s need to be manually initialized, when default-constructed `std::vector`s didn't. Simple oversight.

## PR Checklist
* [x] Closes #8986
* [x] I work here
* [x] A test would be great but ain't nobody got time for that.
* [n/a] Requires documentation to be updated

## Validation Steps Performed
Ran the terminal with
```json

    "schemes" :
    [ {} ]
```
First the crash repro'd, now it doesn't.

(cherry picked from commit 9d71fa817d)
2021-02-04 16:47:55 -08:00
James Holderness
680c7deb2f Fix crash in terminal when tab closed while data is being output (#8982)
If there is data being output when a tab is closed, that can sometimes
result in the application crashing, because the renderer may still be in
use at the time is it destroyed. This PR attempts to prevent that from
happening by adding a lock in the `TermControl::Close` method.

What we're trying to prevent is the connection thread still being
active, and potentially accessing the renderer, after it has been
destroyed. So by acquiring the terminal lock in `TermControl::Close`,
after we've stopped accepting new output, we can be sure that the
connection thread is no longer active (it holds the lock while it is
processing output). So once we've acquired and released the lock, it
should be safe to tear down and destroy the renderer.

## Validation Steps Performed

While this crash is difficult to reproduce in general usage, it occurred
quite frequently when testing my `DECPS` implementation (there is some
tricky thread synchronisation, which seems more likely to trigger the
issue). With this patch applied, though, those crashes have stopped
occurring.

I've also stepped through the shutdown code in the debugger, manually
freezing threads to get them aligned in the right way to trigger the
crash (as explained in issue #8734). Again with the patch applied, I can
no longer get the crash to occur.

Closes #8734

(cherry picked from commit 40ebe5ab54)
2021-02-04 16:47:55 -08:00
hereafter
e9548969e4 Fix crash in explorer background context menu logic (#8977)
Fix a bug brought in with PR: #8638

see,
#8936
#8638

* [x] Closes #8936
* [x] CLA signed
* [x] Tests passed

With the help from @nc-x, the issue is reproduced and fixed by this patch.

CLSCTX_IN_PROCESS is not good enough for all cases to create IShellWindows interface.
Put a CLSCTX_ALL fixes the issue.

Another debugging warning dialogs  for reusing not null com_ptr in the loop is fixed too.
(This was shown in debug builds only)

(cherry picked from commit e207236713)
2021-02-04 16:47:55 -08:00
Carlos Zamora
7fe98a0344 Bind LaunchMode and TabSwitcherMode properly in SUI (#8956)
## Summary of the Pull Request
Properly binds `CurrentLaunchMode` and `CurrentTabSwitcherMode` in the Settings UI. The default mode is `OneTime`, resulting in the setting never being set.

I performed a regex search of all "SelectedItem" bindings and these were the only two that were not properly bound.

## References
#6800 - Settings UI Epic

## Validation Steps Performed
Modified tab switcher mode and launch mode via the settings UI. Then saved. Before, the settings would revert back and not get applied. Now they got applied.

Closes #8947

(cherry picked from commit 597a3325ea)
2021-02-04 16:47:55 -08:00
Kayla Cinnamon
5b1137ccff Add scrollToTop and scrollToBottom actions to JSON schema (#8923)
Closes #8992.

(cherry picked from commit b502e0e530)
2021-02-04 16:47:55 -08:00
Javier
96e0232603 wpf: Add a TerminalControlSize emptiness check (#8906)
Watson reports show that an "ArgumentException" is being thrown due to `renderSize`
not being valid. Added a check for renderSize before attempting to resize.
2021-01-26 13:57:30 -08:00
Carlos Zamora
ae8347f336 Allow ClosePane to close the Settings UI (#8903)
This is an extension of #8885. A lot of users have grown accustomed to
using `closePane` to close a tab. This adds `closePane` to the list of
keybindings accepted by #8885, and modifies the `closePane` code to
close the Settings UI if we are in a `SettingsTab`.

## References

#6800: Settings UI Epic
#8885: PR - Settings UI should respect key bindings (temporary solution)
#8882: Issue - Settings UI should respect key bindings
2021-01-26 19:14:28 +00:00
Mike Griese
3f1262e4c2 Fix the erroneous TargetRuntime causing a warning in VS (#8895)
## Summary of the Pull Request

Apparently, we don't need this `TargetRuntime`. That's what was causing VS to think that we were a C# project, and give us that warning. This is the solution we got from the owner of the `.wapproj` plugin.

## References
* Introduced in c33883d852, in PR #8062

## PR Checklist
* [x] Closes #8301
* [x] I work here


Build and ran it fine. Changed TermControl, built and ran it fine. Now let's hope CI likes it.
2021-01-26 19:13:59 +00:00
PankajBhojwani
b50df20cfe Add a slider for the padding setting in the SUI (#8851)
Replaces the textbox used for the padding setting with a slider

References #8764
2021-01-26 02:22:24 +00:00
Mike Griese
7b6958405e Fix the Profiles pivot selection, again (#8844)
This reverts the revert in #8838.

The problem was that the `Profile` in the singleton nav state would be
updated before the binding fired, so we'd end up modifying the _new_
profile, because both the old page and the new page would be pointing at
the _new_ profile already.

Instead of using a singleton instance of the profile nav state, we'll
create a new one each time. The new nav state attempt to steal the
selected pivot from the last instance of the nav state, if the profiles
are the same. This means that 

This means that we won't end up modifying the new profile. The old
page's nav state will still have the old profile, so it'll still end up
modifying the old `ProfileViewModel`.

## PR Checklist
* [x] I work here
* [x] Tested manually
* [x] Fixes the first point in #8769, again
2021-01-25 15:06:33 -08:00
Don-Vito
65269c8311 Teach SUI tab to respect close / prev / next tab bindings (#8885)
A temporary solution for #8882
2021-01-25 14:52:12 -08:00
Don-Vito
3e5d6e71a2 Fix crash in command palette in high-contrast mode (#8886)
Fixing a typo I made (affecting only high contrast mode)

Closes #8884
2021-01-25 14:51:11 -08:00
Don-Vito
dff8f15efa Teach tab tool tip to show profile name (#8883)
Closes #4478
2021-01-25 22:50:21 +00:00
Dustin Howett
2b27d4ce91 Add DECID to spellbot 2021-01-25 11:38:33 -08:00
James Holderness
172d9a7f64 Add support for the DECID report (#8864)
This PR adds support for the `DECID` (Identify Device) escape sequence,
which allows for querying the terminal type in a way that is backwards
compatible with VT52 terminals.

This simply checks for the `ESC Z` sequence in the `ActionEscDispatch`
method of output state machine, and forwards the query to the existing
`DeviceAttributes` dispatch method, since the expected response is
identical to a `DA` report.

## Validation Steps Performed
I've added an output engine test that verifies that the `ESC Z` sequence
is correctly interpreted as a `DA` query when in ANSI mode, and as a
VT52 identification query when in VT52 mode.

Closes #8857
2021-01-25 18:11:33 +00:00
PankajBhojwani
02fd7a0c15 Show indicator of bell in tab (#8637)
When we emit a BEL (visual or audible), show an indicator in the tab
header

If the tab the BEL is coming from is not focused when the BEL is raised,
the indicator in its header will be removed when the tab gains focus. If
the tab was already focused when the BEL was emitted, then the indicator
goes away after 2 seconds.

Closes #8106
2021-01-22 23:48:20 +00:00
PankajBhojwani
acf36d0e4f sui: Improve the "use parent process directory" checkbox (#8827)
Make the "use parent process directory" checkbox rely on a computed
property in the ProfileViewModel. It will be enabled when the starting
directory is empty and disabled when it's not. When it's unchecked, the
last-used value will be restored. If there is no last-used value, it
will be set to %USERPROFILE%.

Closes #8805
2021-01-22 23:46:41 +00:00
Carlos Zamora
d45cc4c2e1 [Settings UI] Allow renaming a profile (#8837)
This adds a "Name" text box to the Profile page in the Settings UI.
Any changes to the name/icon are propagated to the relevant
NavigationViewItem.

Base Layer does not have a "Name".

## References
#6800 - Settings UI Epic
2021-01-22 23:43:54 +00:00
Carlos Zamora
9700598ecb Bugfix: sync color scheme rename with profile reference (#8793)
## Summary of the Pull Request
This fixes a bug where renaming/deleting a color scheme would not update profiles that referenced it.

This also adds detection for renaming a color scheme to a name that is already in use, and adds appropriate UI for that.

## References
#6800 - Settings UI Epic

## PR Checklist
* [X] Closes #8756 

## Detailed Description of the Pull Request / Additional comments
`Model::CascadiaSettings` was updated to have a `UpdateColorSchemeReferences()` function that updates all profiles referencing the newly renamed color scheme.

`Editor::ColorSchemesPageNavigationState` now takes and exposes a `Model::CascadiaSettings`.

When a color scheme is renamed or deleted, we use `CascadiaSettings` to update our list of color schemes appropriately, then call `UpdateColorSchemeReferences()` to update the profiles.

The tricky part is that `Profile` does not store a direct reference to `ColorScheme`, but rather the name of the color scheme. See [this tread](https://github.com/microsoft/terminal/issues/8756#issuecomment-760375027) for a discussion on this topic.

## Validation Steps Performed
Repro steps from #8756 when renaming/deleting a referenced color scheme.

## Demo
![Scheme Name Already In Use Demo](https://user-images.githubusercontent.com/11050425/105431427-6e023980-5c0a-11eb-894a-42152fc77f05.gif)
2021-01-22 18:21:18 +00:00
Chester Liu
124cbd9e47 Add skeleton code for bracketed paste mode (#8840)
This adds the skeleton code for "bracketed paste mode" to the Windows
Terminal. No actual functionality is implemented yet, just the wiring
for handling DECSET/DECRST 2004.

References #395
Supersedes #7508
2021-01-22 05:11:11 +00:00
Carlos Zamora
b6f5f2a323 Revert "Maintain current Pivot selection... (#8803)" (#8838)
This reverts commit a7d7362b95 introduced by #8803.

Reverting this commit fixes #8836 at the expense of the profile page
remembering the last Pivot selection. The 

## References
#6800 - Settings UI Epic

#8803 maintained a `ProfilePageNavigationState` in `MainPage` to remember
the pivot position. However, the two-way binding on the TextBoxes
now seem to happen too late (after the navigation occurs),
resulting in the text being applied to the wrong profile.  In other
words, the sequence of events probably looks something like this:

1. user types text (_state.profile = old profile)
2. user moves to new profile
3. navigation completes (_state.profile = new profile)
4. textbox two-way binding fires, setting _state.profile.WHATEVER = value

## Validation Steps Performed
Performed repro sets from #8836. Bug no longer occurs. 

Reopens #8769
Closes #8836
2021-01-21 10:50:49 +00:00
Don-Vito
9c4950cb32 Teach terminal to hide mouse while typing (#8629)
## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/issues/5699
* [x] CLA signed. 
* [ ] Tests added/passed
* [ ] Documentation updated. 
* [ ] Schema updated.
* [ ] I've discussed this with core contributors already. 

## Detailed Description of the Pull Request / Additional comments
* Use SPI_GETMOUSEVANISH setting
* Hide upon CharacterReceived
* Unhide upon PointerMoved, PointerMoved, MouseWheel, LoseFocus
2021-01-21 01:17:59 +00:00
Carlos Zamora
3b53c6956c Bugfix: navigate to new profile ref on settings reload (#8835)
Upon a settings reload, we would select the correct navigation item for
a profile, but navigate to the old one. As a result, you would navigate
to the old page that points to a dead profile object. This would make it
appear like you did not discard/save the changes.

This bugfix navigates to the newly created profile, ensuring that your
changes are actually applied to the settings model's clone in use.

## References
#8773 - Introduced the bug
#6800 - Settings UI Epic

## Validation Steps Performed
- Navigate to "powershell" profile
- edit "tab title" value
- discard changes

Before: changes would persist unless you discarded changes again
Now: changes are discarded

Also verified expected behavior occurs when you click "save" instead of
"discard"
2021-01-21 00:54:59 +00:00
Kayla Cinnamon
98d0613124 Include UWP styling guidance in settings UI (#8831)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
The settings UI was _close_ to looking just right, it just needed some tweaks to adhere to the proper guidance: https://docs.microsoft.com/en-us/windows/uwp/design/controls-and-patterns/forms

This PR changes the font sizes, spacing, and layout of all of the pages to align with guidance.

Some pics:
![image](https://user-images.githubusercontent.com/48369326/105241313-58194980-5b22-11eb-9f18-524cc988ec33.png)

![image](https://user-images.githubusercontent.com/48369326/105241331-60718480-5b22-11eb-8698-b9fadf3c3016.png)

![image](https://user-images.githubusercontent.com/48369326/105244413-57ce7d80-5b25-11eb-87c3-ee5f19417318.png)

![image](https://user-images.githubusercontent.com/48369326/105241384-73845480-5b22-11eb-9517-4010b145ffc2.png)

Min width:
![image](https://user-images.githubusercontent.com/48369326/105241406-7aab6280-5b22-11eb-9c59-ffc72f66509d.png)

<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? --> 
## References

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes #8816 
* [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

<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
* Removed custom font sizing, WinUI adheres to guidance anyway
* 24px spacing between controls and 48px between groupings
* Controls shouldn't be next to each other (see Launch size)
* Technically Launch size is a grouping, so it gets upgraded to subtitle status
* Left margins for pages have been fixed to left align with the page titles
* Single checkboxes have been changed to toggle switches

<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2021-01-20 22:42:39 +00:00
Dustin L. Howett
e7592ec3d4 ROW: clean up in preparation to hide CharRow & AttrRow (#8446)
Moving things out of CharRow into ROW helps us hide it as an implementation detail.
This is part one of many.

### CharRow: Hide ClearCell, use ROW::ClearColumn

### CharRow: Hide GetText, use ROW::GetText

### CharRowBaseTests: remove dead file (never used!)

### CharRow: Move DoubleBytePadded into ROW

### CharRow: Move WrapForced into ROW

### Char/AttrRow: Hide Reset, use ROW::Reset

### Remove RowCellIterator (dead code)

RCI was unused; it was replaced by TextBufferCellIterator shortly after its creation

### Move AttrRowTests to ut_textbuffer from ut_host

It had no reliance on the host.
2021-01-20 21:16:56 +00:00
Raphael Horber
b7a7aa0bc3 Add doubleUnderscore cursor style (#7827)
Adds a new cursor type "doubleUnderscore". Tested manually.

Closes #6786
2021-01-20 19:36:07 +00:00
Michael Niksa
0fa286c011 Cleanup NuGet.Config file. (#8829)
Cleans up a ton of competing and outdated sources from our NuGet.Config to improve reliability and maintainability.

## PR Checklist
* [x] Closes an overdue-to-clean mess.
* [x] I work here.
* [x] Tests covered below.
* [x] I've discussed this with @DHowett already.

## Validation Steps Performed
- [x] - NuGet restored everything I could get my hands on (all `packages.config`) in our project before and after the change.
- [x] - The build and tests still run fine. (PR automation should check this one)
2021-01-20 19:00:36 +00:00
Don-Vito
12b12d5b07 Fix tab selection to bring the tab into view (#8832)
## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/issues/3638
* [x] CLA signed.
* [ ] Tests added/passed
* [ ] Documentation updated.
* [ ] Schema updated.
* [x] I've discussed this with core contributors already.

##Detailed Description of the Pull Request / Additional comments
A workaround for https://github.com/microsoft/microsoft-ui-xaml/issues/3945.
Thanks to @michael-hawker and @chingucoding for the suggested solution.
2021-01-20 17:37:47 +00:00
154 changed files with 2340 additions and 2468 deletions

View File

@@ -1,24 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="NuGet.org" value="https://api.nuget.org/v3/index.json" />
<!-- Add repositories here to the list of available repositories -->
<!-- Dependencies that we must carry because they're not on public nuget feeds right now. -->
<clear />
<!-- Dependencies that we can turn on to force override for testing purposes before uploading. -->
<!--<add key="Static Package Dependencies" value="dep\packages" />-->
<!-- Use our own NuGet Feed -->
<add key="TerminalDependencies" value="https://pkgs.dev.azure.com/ms/terminal/_packaging/TerminalDependencies/nuget/v3/index.json" />
<!-- Temporarily? use the feeds from our friends in MUX for Helix test stuff -->
<add key="dotnetfeed" value="https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json" />
<add key="dnceng" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json" />
<add key="MUX-Dependencies" value="https://pkgs.dev.azure.com/ms/microsoft-ui-xaml/_packaging/MUX-Dependencies/nuget/v3/index.json" />
<!-- Internal NuGet feeds that may not be accessible outside Microsoft corporate network -->
<!--<add key="TAEF - internal" value="https://microsoft.pkgs.visualstudio.com/DefaultCollection/_packaging/Taef/nuget/v3/index.json" />
<add key="OpenConsole - Internal" value="https://microsoft.pkgs.visualstudio.com/_packaging/OpenConsole/nuget/v3/index.json" />-->
</packageSources>
<disabledPackageSources>
<clear />
</disabledPackageSources>
<config>
<add key="repositorypath" value=".\packages" />
</config>

View File

@@ -232,16 +232,9 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnitTests_TerminalApp", "sr
{CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907} = {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CommandlineArgs", "src\cascadia\CommandlineArgs\CommandlineArgs.vcxproj", "{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}"
ProjectSection(ProjectDependencies) = postProject
{CA5CAD1A-082C-4476-9F33-94B339494076} = {CA5CAD1A-082C-4476-9F33-94B339494076}
{CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED} = {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalAppLib", "src\cascadia\TerminalApp\TerminalAppLib.vcxproj", "{CA5CAD1A-9A12-429C-B551-8562EC954746}"
ProjectSection(ProjectDependencies) = postProject
{CA5CAD1A-082C-4476-9F33-94B339494076} = {CA5CAD1A-082C-4476-9F33-94B339494076}
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA} = {2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}
{CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} = {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}
{CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED} = {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}
EndProjectSection
@@ -1778,33 +1771,6 @@ Global
{CA5CAD1A-9333-4D05-B12A-1905CBF112F9}.Release|x64.Build.0 = Release|x64
{CA5CAD1A-9333-4D05-B12A-1905CBF112F9}.Release|x86.ActiveCfg = Release|Win32
{CA5CAD1A-9333-4D05-B12A-1905CBF112F9}.Release|x86.Build.0 = Release|Win32
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.AuditMode|Any CPU.ActiveCfg = AuditMode|Win32
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.AuditMode|ARM.ActiveCfg = AuditMode|Win32
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.AuditMode|DotNet_x64Test.ActiveCfg = AuditMode|Win32
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.AuditMode|DotNet_x86Test.ActiveCfg = AuditMode|Win32
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.AuditMode|x64.ActiveCfg = AuditMode|x64
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.AuditMode|x86.ActiveCfg = AuditMode|Win32
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.Debug|Any CPU.ActiveCfg = Debug|Win32
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.Debug|ARM.ActiveCfg = Debug|Win32
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.Debug|ARM64.ActiveCfg = Debug|ARM64
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.Debug|ARM64.Build.0 = Debug|ARM64
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.Debug|DotNet_x64Test.ActiveCfg = Debug|Win32
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.Debug|DotNet_x86Test.ActiveCfg = Debug|Win32
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.Debug|x64.ActiveCfg = Debug|x64
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.Debug|x64.Build.0 = Debug|x64
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.Debug|x86.ActiveCfg = Debug|Win32
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.Debug|x86.Build.0 = Debug|Win32
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.Release|Any CPU.ActiveCfg = Release|Win32
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.Release|ARM.ActiveCfg = Release|Win32
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.Release|ARM64.ActiveCfg = Release|ARM64
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.Release|ARM64.Build.0 = Release|ARM64
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.Release|DotNet_x64Test.ActiveCfg = Release|Win32
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.Release|DotNet_x86Test.ActiveCfg = Release|Win32
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.Release|x64.ActiveCfg = Release|x64
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.Release|x64.Build.0 = Release|x64
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.Release|x86.ActiveCfg = Release|Win32
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.Release|x86.Build.0 = Release|Win32
{CA5CAD1A-9A12-429C-B551-8562EC954746}.AuditMode|Any CPU.ActiveCfg = Debug|Win32
{CA5CAD1A-9A12-429C-B551-8562EC954746}.AuditMode|ARM.ActiveCfg = AuditMode|Win32
{CA5CAD1A-9A12-429C-B551-8562EC954746}.AuditMode|ARM64.ActiveCfg = Release|ARM64
@@ -2440,8 +2406,6 @@ Global
{21B7EA5E-1EF8-49B6-AC07-11714AF0E37D}.Release|x86.ActiveCfg = Release|Win32
{21B7EA5E-1EF8-49B6-AC07-11714AF0E37D}.Release|x86.Build.0 = Release|Win32
{F75E29D0-D288-478B-8D83-2C190F321A3F}.AuditMode|Any CPU.ActiveCfg = Release|Any CPU
{F75E29D0-D288-478B-8D83-2C190F321A3F}.AuditMode|Any CPU.Build.0 = Release|Any CPU
{F75E29D0-D288-478B-8D83-2C190F321A3F}.AuditMode|Any CPU.Deploy.0 = Release|Any CPU
{F75E29D0-D288-478B-8D83-2C190F321A3F}.AuditMode|ARM.ActiveCfg = Debug|ARM
{F75E29D0-D288-478B-8D83-2C190F321A3F}.AuditMode|ARM.Build.0 = Debug|ARM
{F75E29D0-D288-478B-8D83-2C190F321A3F}.AuditMode|ARM.Deploy.0 = Debug|ARM
@@ -2449,11 +2413,7 @@ Global
{F75E29D0-D288-478B-8D83-2C190F321A3F}.AuditMode|ARM64.Build.0 = Debug|ARM64
{F75E29D0-D288-478B-8D83-2C190F321A3F}.AuditMode|ARM64.Deploy.0 = Debug|ARM64
{F75E29D0-D288-478B-8D83-2C190F321A3F}.AuditMode|DotNet_x64Test.ActiveCfg = Release|Any CPU
{F75E29D0-D288-478B-8D83-2C190F321A3F}.AuditMode|DotNet_x64Test.Build.0 = Release|Any CPU
{F75E29D0-D288-478B-8D83-2C190F321A3F}.AuditMode|DotNet_x64Test.Deploy.0 = Release|Any CPU
{F75E29D0-D288-478B-8D83-2C190F321A3F}.AuditMode|DotNet_x86Test.ActiveCfg = Release|Any CPU
{F75E29D0-D288-478B-8D83-2C190F321A3F}.AuditMode|DotNet_x86Test.Build.0 = Release|Any CPU
{F75E29D0-D288-478B-8D83-2C190F321A3F}.AuditMode|DotNet_x86Test.Deploy.0 = Release|Any CPU
{F75E29D0-D288-478B-8D83-2C190F321A3F}.AuditMode|x64.ActiveCfg = Debug|x64
{F75E29D0-D288-478B-8D83-2C190F321A3F}.AuditMode|x64.Build.0 = Debug|x64
{F75E29D0-D288-478B-8D83-2C190F321A3F}.AuditMode|x64.Deploy.0 = Debug|x64
@@ -2461,8 +2421,6 @@ Global
{F75E29D0-D288-478B-8D83-2C190F321A3F}.AuditMode|x86.Build.0 = Debug|x86
{F75E29D0-D288-478B-8D83-2C190F321A3F}.AuditMode|x86.Deploy.0 = Debug|x86
{F75E29D0-D288-478B-8D83-2C190F321A3F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F75E29D0-D288-478B-8D83-2C190F321A3F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F75E29D0-D288-478B-8D83-2C190F321A3F}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{F75E29D0-D288-478B-8D83-2C190F321A3F}.Debug|ARM.ActiveCfg = Debug|ARM
{F75E29D0-D288-478B-8D83-2C190F321A3F}.Debug|ARM.Build.0 = Debug|ARM
{F75E29D0-D288-478B-8D83-2C190F321A3F}.Debug|ARM.Deploy.0 = Debug|ARM
@@ -2470,11 +2428,7 @@ Global
{F75E29D0-D288-478B-8D83-2C190F321A3F}.Debug|ARM64.Build.0 = Debug|ARM64
{F75E29D0-D288-478B-8D83-2C190F321A3F}.Debug|ARM64.Deploy.0 = Debug|ARM64
{F75E29D0-D288-478B-8D83-2C190F321A3F}.Debug|DotNet_x64Test.ActiveCfg = Debug|Any CPU
{F75E29D0-D288-478B-8D83-2C190F321A3F}.Debug|DotNet_x64Test.Build.0 = Debug|Any CPU
{F75E29D0-D288-478B-8D83-2C190F321A3F}.Debug|DotNet_x64Test.Deploy.0 = Debug|Any CPU
{F75E29D0-D288-478B-8D83-2C190F321A3F}.Debug|DotNet_x86Test.ActiveCfg = Debug|Any CPU
{F75E29D0-D288-478B-8D83-2C190F321A3F}.Debug|DotNet_x86Test.Build.0 = Debug|Any CPU
{F75E29D0-D288-478B-8D83-2C190F321A3F}.Debug|DotNet_x86Test.Deploy.0 = Debug|Any CPU
{F75E29D0-D288-478B-8D83-2C190F321A3F}.Debug|x64.ActiveCfg = Debug|x64
{F75E29D0-D288-478B-8D83-2C190F321A3F}.Debug|x64.Build.0 = Debug|x64
{F75E29D0-D288-478B-8D83-2C190F321A3F}.Debug|x64.Deploy.0 = Debug|x64
@@ -2482,8 +2436,6 @@ Global
{F75E29D0-D288-478B-8D83-2C190F321A3F}.Debug|x86.Build.0 = Debug|x86
{F75E29D0-D288-478B-8D83-2C190F321A3F}.Debug|x86.Deploy.0 = Debug|x86
{F75E29D0-D288-478B-8D83-2C190F321A3F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F75E29D0-D288-478B-8D83-2C190F321A3F}.Release|Any CPU.Build.0 = Release|Any CPU
{F75E29D0-D288-478B-8D83-2C190F321A3F}.Release|Any CPU.Deploy.0 = Release|Any CPU
{F75E29D0-D288-478B-8D83-2C190F321A3F}.Release|ARM.ActiveCfg = Release|ARM
{F75E29D0-D288-478B-8D83-2C190F321A3F}.Release|ARM.Build.0 = Release|ARM
{F75E29D0-D288-478B-8D83-2C190F321A3F}.Release|ARM.Deploy.0 = Release|ARM
@@ -2491,11 +2443,7 @@ Global
{F75E29D0-D288-478B-8D83-2C190F321A3F}.Release|ARM64.Build.0 = Release|ARM64
{F75E29D0-D288-478B-8D83-2C190F321A3F}.Release|ARM64.Deploy.0 = Release|ARM64
{F75E29D0-D288-478B-8D83-2C190F321A3F}.Release|DotNet_x64Test.ActiveCfg = Release|Any CPU
{F75E29D0-D288-478B-8D83-2C190F321A3F}.Release|DotNet_x64Test.Build.0 = Release|Any CPU
{F75E29D0-D288-478B-8D83-2C190F321A3F}.Release|DotNet_x64Test.Deploy.0 = Release|Any CPU
{F75E29D0-D288-478B-8D83-2C190F321A3F}.Release|DotNet_x86Test.ActiveCfg = Release|Any CPU
{F75E29D0-D288-478B-8D83-2C190F321A3F}.Release|DotNet_x86Test.Build.0 = Release|Any CPU
{F75E29D0-D288-478B-8D83-2C190F321A3F}.Release|DotNet_x86Test.Deploy.0 = Release|Any CPU
{F75E29D0-D288-478B-8D83-2C190F321A3F}.Release|x64.ActiveCfg = Release|x64
{F75E29D0-D288-478B-8D83-2C190F321A3F}.Release|x64.Build.0 = Release|x64
{F75E29D0-D288-478B-8D83-2C190F321A3F}.Release|x64.Deploy.0 = Release|x64
@@ -2509,7 +2457,7 @@ Global
{43CE4CE5-0010-4B99-9569-672670D26E26}.AuditMode|DotNet_x64Test.ActiveCfg = AuditMode|Win32
{43CE4CE5-0010-4B99-9569-672670D26E26}.AuditMode|DotNet_x86Test.ActiveCfg = AuditMode|Win32
{43CE4CE5-0010-4B99-9569-672670D26E26}.AuditMode|x64.ActiveCfg = Release|x64
{43CE4CE5-0010-4B99-9569-672670D26E26}.AuditMode|x64.Build.0 = Release|x64
{43CE4CE5-0010-4B99-9569-672670D26E26}.AuditMode|x64.Build.0 = AuditMode|x64
{43CE4CE5-0010-4B99-9569-672670D26E26}.AuditMode|x86.ActiveCfg = AuditMode|Win32
{43CE4CE5-0010-4B99-9569-672670D26E26}.AuditMode|x86.Build.0 = AuditMode|Win32
{43CE4CE5-0010-4B99-9569-672670D26E26}.Debug|Any CPU.ActiveCfg = Debug|Win32
@@ -2650,7 +2598,6 @@ Global
{84848BFA-931D-42CE-9ADF-01EE54DE7890} = {59840756-302F-44DF-AA47-441A9D673202}
{376FE273-6B84-4EB5-8B30-8DE9D21B022C} = {59840756-302F-44DF-AA47-441A9D673202}
{CA5CAD1A-9333-4D05-B12A-1905CBF112F9} = {BDB237B6-1D1D-400F-84CC-40A58FA59C8E}
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA} = {59840756-302F-44DF-AA47-441A9D673202}
{CA5CAD1A-9A12-429C-B551-8562EC954746} = {59840756-302F-44DF-AA47-441A9D673202}
{CA5CAD1A-B11C-4DDB-A4FE-C3AFAE9B5506} = {BDB237B6-1D1D-400F-84CC-40A58FA59C8E}
{48D21369-3D7B-4431-9967-24E81292CF63} = {05500DEF-2294-41E3-AF9A-24E580B82836}

View File

@@ -93,6 +93,8 @@
"scrollDownPage",
"scrollUp",
"scrollUpPage",
"scrollToBottom",
"scrollToTop",
"sendInput",
"setColorScheme",
"setTabColor",
@@ -933,9 +935,10 @@
},
"cursorShape": {
"default": "bar",
"description": "Sets the shape of the cursor. Possible values:\n -\"bar\" ( ┃, default )\n -\"emptyBox\" ( ▯ )\n -\"filledBox\" ( █ )\n -\"underscore\" ( ▁ )\n -\"vintage\" ( ▃ )",
"description": "Sets the shape of the cursor. Possible values:\n -\"bar\" ( ┃, default )\n -\"doubleUnderscore\" ( ‗ )\n -\"emptyBox\" ( ▯ )\n -\"filledBox\" ( █ )\n -\"underscore\" ( ▁ )\n -\"vintage\" ( ▃ )",
"enum": [
"bar",
"doubleUnderscore",
"emptyBox",
"filledBox",
"underscore",

Binary file not shown.

Binary file not shown.

View File

@@ -17,5 +17,5 @@ Please consult the [license](https://raw.githubusercontent.com/microsoft/cascadi
### Fonts Included
* Cascadia Code, Cascadia Mono (2009.21)
* from microsoft/cascadia-code@32f84124db1970fa5d032f0fe9019e6922961beb
* Cascadia Code, Cascadia Mono (2102.25)
* from microsoft/cascadia-code@911dc421f333e3b72b97381d16fee5b71eb48f04

View File

@@ -39,8 +39,6 @@ public:
noexcept = default;
ATTR_ROW& operator=(ATTR_ROW&&) noexcept = default;
void Reset(const TextAttribute attr);
TextAttribute GetAttrByColumn(const size_t column) const;
TextAttribute GetAttrByColumn(const size_t column,
size_t* const pApplies) const;
@@ -72,12 +70,16 @@ public:
friend bool operator==(const ATTR_ROW& a, const ATTR_ROW& b) noexcept;
friend class AttrRowIterator;
friend class ROW;
private:
void Reset(const TextAttribute attr);
boost::container::small_vector<TextAttributeRun, 1> _list;
size_t _cchRowWidth;
#ifdef UNIT_TESTING
friend class AttrRowTests;
friend class CommonState;
#endif
};

View File

@@ -18,58 +18,12 @@
#pragma warning(push)
#pragma warning(disable : 26447) // small_vector's constructor says it can throw but it should not given how we use it. This suppresses this error for the AuditMode build.
CharRow::CharRow(size_t rowWidth, ROW* const pParent) noexcept :
_wrapForced{ false },
_doubleBytePadded{ false },
_data(rowWidth, value_type()),
_pParent{ FAIL_FAST_IF_NULL(pParent) }
{
}
#pragma warning(pop)
// Routine Description:
// - Sets the wrap status for the current row
// Arguments:
// - wrapForced - True if the row ran out of space and we forced to wrap to the next row. False otherwise.
// Return Value:
// - <none>
void CharRow::SetWrapForced(const bool wrapForced) noexcept
{
_wrapForced = wrapForced;
}
// Routine Description:
// - Gets the wrap status for the current row
// Arguments:
// - <none>
// Return Value:
// - True if the row ran out of space and we were forced to wrap to the next row. False otherwise.
bool CharRow::WasWrapForced() const noexcept
{
return _wrapForced;
}
// Routine Description:
// - Sets the double byte padding for the current row
// Arguments:
// - fWrapWasForced - True if the row ran out of space for a double byte character and we padded out the row. False otherwise.
// Return Value:
// - <none>
void CharRow::SetDoubleBytePadded(const bool doubleBytePadded) noexcept
{
_doubleBytePadded = doubleBytePadded;
}
// Routine Description:
// - Gets the double byte padding status for the current row.
// Arguments:
// - <none>
// Return Value:
// - True if the row didn't have space for a double byte character and we were padded out the row. False otherwise.
bool CharRow::WasDoubleBytePadded() const noexcept
{
return _doubleBytePadded;
}
// Routine Description:
// - gets the size of the row, in glyph cells
// Arguments:
@@ -93,9 +47,6 @@ void CharRow::Reset() noexcept
{
cell.Reset();
}
_wrapForced = false;
_doubleBytePadded = false;
}
// Routine Description:

View File

@@ -56,21 +56,14 @@ public:
CharRow(size_t rowWidth, ROW* const pParent) noexcept;
void SetWrapForced(const bool wrap) noexcept;
bool WasWrapForced() const noexcept;
void SetDoubleBytePadded(const bool doubleBytePadded) noexcept;
bool WasDoubleBytePadded() const noexcept;
size_t size() const noexcept;
void Reset() noexcept;
[[nodiscard]] HRESULT Resize(const size_t newSize) noexcept;
size_t MeasureLeft() const noexcept;
size_t MeasureRight() const;
void ClearCell(const size_t column);
bool ContainsText() const noexcept;
const DbcsAttribute& DbcsAttrAt(const size_t column) const;
DbcsAttribute& DbcsAttrAt(const size_t column);
void ClearGlyph(const size_t column);
std::wstring GetText() const;
const DelimiterClass DelimiterClassAt(const size_t column, const std::wstring_view wordDelimiters) const;
@@ -94,15 +87,14 @@ public:
void UpdateParent(ROW* const pParent);
friend CharRowCellReference;
friend constexpr bool operator==(const CharRow& a, const CharRow& b) noexcept;
friend class ROW;
private:
void Reset() noexcept;
void ClearCell(const size_t column);
std::wstring GetText() const;
protected:
// Occurs when the user runs out of text in a given row and we're forced to wrap the cursor to the next line
bool _wrapForced;
// Occurs when the user runs out of text to support a double byte character and we're forced to the next line
bool _doubleBytePadded;
// storage for glyph data and dbcs attributes
boost::container::small_vector<value_type, 120> _data;
@@ -110,13 +102,6 @@ protected:
ROW* _pParent;
};
constexpr bool operator==(const CharRow& a, const CharRow& b) noexcept
{
return (a._wrapForced == b._wrapForced &&
a._doubleBytePadded == b._doubleBytePadded &&
a._data == b._data);
}
template<typename InputIt1, typename InputIt2>
void OverwriteColumns(InputIt1 startChars, InputIt1 endChars, InputIt2 startAttrs, CharRow::iterator outIt)
{

View File

@@ -21,6 +21,8 @@ ROW::ROW(const SHORT rowId, const unsigned short rowWidth, const TextAttribute f
_rowWidth{ rowWidth },
_charRow{ rowWidth, this },
_attrRow{ rowWidth, fillAttribute },
_wrapForced{ false },
_doubleBytePadded{ false },
_pParent{ pParent }
{
}
@@ -33,6 +35,8 @@ ROW::ROW(const SHORT rowId, const unsigned short rowWidth, const TextAttribute f
// - <none>
bool ROW::Reset(const TextAttribute Attr)
{
_wrapForced = false;
_doubleBytePadded = false;
_charRow.Reset();
try
{
@@ -159,7 +163,7 @@ OutputCellIterator ROW::WriteCells(OutputCellIterator it, const size_t index, co
else if (fillingLastColumn && it->DbcsAttr().IsLeading())
{
_charRow.ClearCell(currentIndex);
_charRow.SetDoubleBytePadded(true);
SetDoubleBytePadded(true);
}
// Otherwise, copy the data given and increment the iterator.
else
@@ -177,7 +181,7 @@ OutputCellIterator ROW::WriteCells(OutputCellIterator it, const size_t index, co
if (wrap.has_value() && fillingLastColumn)
{
// set wrap status on the row to parameter's value.
_charRow.SetWrapForced(wrap.value());
SetWrapForced(*wrap);
}
}
else

View File

@@ -24,7 +24,6 @@ Revision History:
#include "OutputCell.hpp"
#include "OutputCellIterator.hpp"
#include "CharRow.hpp"
#include "RowCellIterator.hpp"
#include "UnicodeStorage.hpp"
class TextBuffer;
@@ -37,6 +36,12 @@ public:
size_t size() const noexcept { return _rowWidth; }
void SetWrapForced(const bool wrap) noexcept { _wrapForced = wrap; }
bool WasWrapForced() const noexcept { return _wrapForced; }
void SetDoubleBytePadded(const bool doubleBytePadded) noexcept { _doubleBytePadded = doubleBytePadded; }
bool WasDoubleBytePadded() const noexcept { return _doubleBytePadded; }
const CharRow& GetCharRow() const noexcept { return _charRow; }
CharRow& GetCharRow() noexcept { return _charRow; }
@@ -52,17 +57,13 @@ public:
void ClearColumn(const size_t column);
std::wstring GetText() const { return _charRow.GetText(); }
RowCellIterator AsCellIter(const size_t startIndex) const { return AsCellIter(startIndex, size() - startIndex); }
RowCellIterator AsCellIter(const size_t startIndex, const size_t count) const { return RowCellIterator(*this, startIndex, count); }
UnicodeStorage& GetUnicodeStorage() noexcept;
const UnicodeStorage& GetUnicodeStorage() const noexcept;
OutputCellIterator WriteCells(OutputCellIterator it, const size_t index, const std::optional<bool> wrap = std::nullopt, std::optional<size_t> limitRight = std::nullopt);
friend bool operator==(const ROW& a, const ROW& b) noexcept;
#ifdef UNIT_TESTING
friend constexpr bool operator==(const ROW& a, const ROW& b) noexcept;
friend class RowTests;
#endif
@@ -71,14 +72,18 @@ private:
ATTR_ROW _attrRow;
SHORT _id;
unsigned short _rowWidth;
// Occurs when the user runs out of text in a given row and we're forced to wrap the cursor to the next line
bool _wrapForced;
// Occurs when the user runs out of text to support a double byte character and we're forced to the next line
bool _doubleBytePadded;
TextBuffer* _pParent; // non ownership pointer
};
inline bool operator==(const ROW& a, const ROW& b) noexcept
#ifdef UNIT_TESTING
constexpr bool operator==(const ROW& a, const ROW& b) noexcept
{
return (a._charRow == b._charRow &&
a._attrRow == b._attrRow &&
a._rowWidth == b._rowWidth &&
a._pParent == b._pParent &&
// comparison is only used in the tests; this should suffice.
return (a._pParent == b._pParent &&
a._id == b._id);
}
#endif

View File

@@ -1,110 +0,0 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "precomp.h"
#include "RowCellIterator.hpp"
#include "Row.hpp"
#include "../../types/inc/convert.hpp"
#include "../../types/inc/Utf16Parser.hpp"
RowCellIterator::RowCellIterator(const ROW& row, const size_t start, const size_t length) :
_row(row),
_start(start),
_length(length),
_pos(start),
_view(s_GenerateView(row, start))
{
}
RowCellIterator::operator bool() const noexcept
{
// In lieu of using start and end, this custom iterator type simply becomes bool false
// when we run out of items to iterate over.
return _pos < (_start + _length);
}
bool RowCellIterator::operator==(const RowCellIterator& it) const noexcept
{
return _row == it._row &&
_start == it._start &&
_length == it._length &&
_pos == it._pos;
}
bool RowCellIterator::operator!=(const RowCellIterator& it) const noexcept
{
return !(*this == it);
}
RowCellIterator& RowCellIterator::operator+=(const ptrdiff_t& movement) noexcept
{
_pos += movement;
return (*this);
}
RowCellIterator& RowCellIterator::operator++() noexcept
{
return this->operator+=(1);
}
RowCellIterator RowCellIterator::operator++(int) noexcept
{
auto temp(*this);
operator++();
return temp;
}
RowCellIterator RowCellIterator::operator+(const ptrdiff_t& movement) noexcept
{
auto temp(*this);
temp += movement;
return temp;
}
const OutputCellView& RowCellIterator::operator*() const noexcept
{
return _view;
}
const OutputCellView* RowCellIterator::operator->() const noexcept
{
return &_view;
}
// Routine Description:
// - Member function to update the view to the current position in the buffer with
// the data held on this object.
// Arguments:
// - <none>
// Return Value:
// - <none>
void RowCellIterator::_RefreshView()
{
_view = s_GenerateView(_row, _pos);
}
// Routine Description:
// - Static function to create a view.
// - It's pulled out statically so it can be used during construction with just the given
// variables (so OutputCellView doesn't need an empty default constructor)
// - This will infer the width of the glyph and apply the appropriate attributes to the view.
// Arguments:
// - view - View representing characters corresponding to a single glyph
// - attr - Color attributes to apply to the text
// Return Value:
// - Object representing the view into this cell
OutputCellView RowCellIterator::s_GenerateView(const ROW& row,
const size_t pos)
{
const auto& charRow = row.GetCharRow();
const auto glyph = charRow.GlyphAt(pos);
const auto dbcsAttr = charRow.DbcsAttrAt(pos);
const auto textAttr = row.GetAttrRow().GetAttrByColumn(pos);
const auto behavior = TextAttributeBehavior::Stored;
return OutputCellView(glyph, dbcsAttr, textAttr, behavior);
}

View File

@@ -1,59 +0,0 @@
/*++
Copyright (c) Microsoft Corporation
Licensed under the MIT license.
Module Name:
- RowCellIterator.hpp
Abstract:
- Read-only view into cells already in the input buffer.
- This is done for performance reasons (avoid heap allocs and copies).
Author:
- Michael Niksa (MiNiksa) 12-Oct-2018
--*/
#pragma once
#include "OutputCellView.hpp"
class ROW;
class RowCellIterator final
{
public:
using iterator_category = std::forward_iterator_tag;
using value_type = OutputCellView;
using difference_type = ptrdiff_t;
using pointer = OutputCellView*;
using reference = OutputCellView&;
RowCellIterator(const ROW& row, const size_t start, const size_t length);
~RowCellIterator() = default;
RowCellIterator& operator=(const RowCellIterator& it) = delete;
operator bool() const noexcept;
bool operator==(const RowCellIterator& it) const noexcept;
bool operator!=(const RowCellIterator& it) const noexcept;
RowCellIterator& operator+=(const ptrdiff_t& movement) noexcept;
RowCellIterator& operator++() noexcept;
RowCellIterator operator++(int) noexcept;
RowCellIterator operator+(const ptrdiff_t& movement) noexcept;
const OutputCellView& operator*() const noexcept;
const OutputCellView* operator->() const noexcept;
private:
const ROW& _row;
const size_t _start;
const size_t _length;
size_t _pos;
OutputCellView _view;
void _RefreshView();
static OutputCellView s_GenerateView(const ROW& row, const size_t pos);
};

View File

@@ -18,7 +18,6 @@
<ClCompile Include="..\OutputCellRect.cpp" />
<ClCompile Include="..\OutputCellView.cpp" />
<ClCompile Include="..\Row.cpp" />
<ClCompile Include="..\RowCellIterator.cpp" />
<ClCompile Include="..\search.cpp" />
<ClCompile Include="..\TextColor.cpp" />
<ClCompile Include="..\TextAttribute.cpp" />
@@ -44,7 +43,6 @@
<ClInclude Include="..\OutputCellRect.hpp" />
<ClInclude Include="..\OutputCellView.hpp" />
<ClInclude Include="..\Row.hpp" />
<ClInclude Include="..\RowCellIterator.hpp" />
<ClInclude Include="..\search.h" />
<ClInclude Include="..\TextColor.h" />
<ClInclude Include="..\TextAttribute.h" />
@@ -60,4 +58,4 @@
</ItemGroup>
<!-- Careful reordering these. Some default props (contained in these files) are order sensitive. -->
<Import Project="$(SolutionDir)src\common.build.post.props" />
</Project>
</Project>

View File

@@ -37,7 +37,6 @@ SOURCES= \
..\OutputCellRect.cpp \
..\OutputCellView.cpp \
..\Row.cpp \
..\RowCellIterator.cpp \
..\TextColor.cpp \
..\TextAttribute.cpp \
..\textBuffer.cpp \

View File

@@ -254,7 +254,7 @@ bool TextBuffer::_AssertValidDoubleByteSequence(const DbcsAttribute dbcsAttribut
// Erase previous character into an N type.
try
{
prevRow.GetCharRow().ClearCell(coordPrevPosition.X);
prevRow.ClearColumn(coordPrevPosition.X);
}
catch (...)
{
@@ -296,8 +296,8 @@ bool TextBuffer::_PrepareForDoubleByteSequence(const DbcsAttribute dbcsAttribute
if (GetCursor().GetPosition().X == sBufferWidth - 1)
{
// set that we're wrapping for double byte reasons
CharRow& charRow = GetRowByOffset(GetCursor().GetPosition().Y).GetCharRow();
charRow.SetDoubleBytePadded(true);
auto& row = GetRowByOffset(GetCursor().GetPosition().Y);
row.SetDoubleBytePadded(true);
// then move the cursor forward and onto the next row
fSuccess = IncrementCursor();
@@ -480,7 +480,7 @@ void TextBuffer::_AdjustWrapOnCurrentRow(const bool fSet)
const UINT uiCurrentRowOffset = GetCursor().GetPosition().Y;
// Set the wrap status as appropriate
GetRowByOffset(uiCurrentRowOffset).GetCharRow().SetWrapForced(fSet);
GetRowByOffset(uiCurrentRowOffset).SetWrapForced(fSet);
}
//Routine Description:
@@ -810,8 +810,7 @@ void TextBuffer::Reset()
for (auto& row : _storage)
{
row.GetCharRow().Reset();
row.GetAttrRow().Reset(attr);
row.Reset(attr);
}
}
@@ -1588,7 +1587,7 @@ const TextBuffer::TextAndColor TextBuffer::GetText(const bool includeCRLF,
}
// We apply formatting to rows if the row was NOT wrapped or formatting of wrapped rows is allowed
const bool shouldFormatRow = formatWrappedRows || !GetRowByOffset(iRow).GetCharRow().WasWrapForced();
const bool shouldFormatRow = formatWrappedRows || !GetRowByOffset(iRow).WasWrapForced();
if (trimTrailingWhitespace)
{
@@ -2069,7 +2068,7 @@ HRESULT TextBuffer::Reflow(TextBuffer& oldBuffer,
// included.)
// As such, adjust the "right" to be the width of the row
// to capture all these spaces
if (charRow.WasWrapForced())
if (row.WasWrapForced())
{
iRight = cOldColsTotal;
@@ -2078,7 +2077,7 @@ HRESULT TextBuffer::Reflow(TextBuffer& oldBuffer,
// piece of padding because of a double byte LEADING
// character, then remove one from the "right" to
// leave this padding out of the copy process.
if (charRow.WasDoubleBytePadded())
if (row.WasDoubleBytePadded())
{
iRight--;
}
@@ -2142,7 +2141,7 @@ HRESULT TextBuffer::Reflow(TextBuffer& oldBuffer,
// Only do so if we were not forced to wrap. If we did
// force a word wrap, then the existing line break was
// only because we ran out of space.
if (iRight < cOldColsTotal && !charRow.WasWrapForced())
if (iRight < cOldColsTotal && !row.WasWrapForced())
{
if (iRight == cOldCursorPos.X && iOldRow == cOldCursorPos.Y)
{
@@ -2186,7 +2185,7 @@ HRESULT TextBuffer::Reflow(TextBuffer& oldBuffer,
const COORD coordNewCursor = newCursor.GetPosition();
if (coordNewCursor.X == 0 && coordNewCursor.Y > 0)
{
if (newBuffer.GetRowByOffset(gsl::narrow_cast<size_t>(coordNewCursor.Y) - 1).GetCharRow().WasWrapForced())
if (newBuffer.GetRowByOffset(gsl::narrow_cast<size_t>(coordNewCursor.Y) - 1).WasWrapForced())
{
hr = newBuffer.NewlineCursor() ? hr : E_OUTOFMEMORY;
}
@@ -2219,7 +2218,7 @@ HRESULT TextBuffer::Reflow(TextBuffer& oldBuffer,
// If the last row of the new buffer wrapped, there's going to be one less newline needed,
// because the cursor is already on the next line
if (newBuffer.GetRowByOffset(cNewLastChar.Y).GetCharRow().WasWrapForced())
if (newBuffer.GetRowByOffset(cNewLastChar.Y).WasWrapForced())
{
iNewlines = std::max(iNewlines - 1, 0);
}
@@ -2227,7 +2226,7 @@ HRESULT TextBuffer::Reflow(TextBuffer& oldBuffer,
{
// if this buffer didn't wrap, but the old one DID, then the d(columns) of the
// old buffer will be one more than in this buffer, so new need one LESS.
if (oldBuffer.GetRowByOffset(cOldLastChar.Y).GetCharRow().WasWrapForced())
if (oldBuffer.GetRowByOffset(cOldLastChar.Y).WasWrapForced())
{
iNewlines = std::max(iNewlines - 1, 0);
}
@@ -2417,7 +2416,7 @@ PointTree TextBuffer::GetPatterns(const size_t firstRow, const size_t lastRow) c
for (auto i = firstRow; i <= lastRow; ++i)
{
auto& row = GetRowByOffset(i);
concatAll += row.GetCharRow().GetText();
concatAll += row.GetText();
}
// for each pattern we know of, iterate through the string

View File

@@ -3,14 +3,9 @@
#include "precomp.h"
#include "WexTestClass.h"
#include "../../inc/consoletaeftemplates.hpp"
#include "../../../inc/consoletaeftemplates.hpp"
#include "CommonState.hpp"
#include "globals.h"
#include "../buffer/out/textBuffer.hpp"
#include "input.h"
#include "../textBuffer.hpp"
using namespace WEX::Common;
using namespace WEX::Logging;
@@ -170,64 +165,54 @@ class AttrRowTests
_Inout_ std::unique_ptr<TextAttributeRun[]>& outAttrRun,
_Out_ size_t* const cOutAttrRun)
{
NTSTATUS status = STATUS_SUCCESS;
RETURN_HR_IF(E_NOT_SUFFICIENT_BUFFER, cRowLength == 0);
if (cRowLength == 0)
// first count up the deltas in the array
size_t cDeltas = 1;
const TextAttribute* pPrevAttr = &rgAttrs[0];
for (size_t i = 1; i < cRowLength; i++)
{
status = STATUS_BUFFER_TOO_SMALL;
}
const TextAttribute* pCurAttr = &rgAttrs[i];
if (NT_SUCCESS(status))
{
// first count up the deltas in the array
size_t cDeltas = 1;
const TextAttribute* pPrevAttr = &rgAttrs[0];
for (size_t i = 1; i < cRowLength; i++)
if (*pCurAttr != *pPrevAttr)
{
const TextAttribute* pCurAttr = &rgAttrs[i];
if (*pCurAttr != *pPrevAttr)
{
cDeltas++;
}
pPrevAttr = pCurAttr;
cDeltas++;
}
// This whole situation was too complicated with a one off holder for one row run
// new method:
// delete the old buffer
// make a new buffer, one run + one run for each change
// set the values for each run one run index at a time
pPrevAttr = pCurAttr;
}
std::unique_ptr<TextAttributeRun[]> attrRun = std::make_unique<TextAttributeRun[]>(cDeltas);
status = NT_TESTNULL(attrRun.get());
if (NT_SUCCESS(status))
// This whole situation was too complicated with a one off holder for one row run
// new method:
// delete the old buffer
// make a new buffer, one run + one run for each change
// set the values for each run one run index at a time
std::unique_ptr<TextAttributeRun[]> attrRun = std::make_unique<TextAttributeRun[]>(cDeltas);
RETURN_HR_IF_NULL(E_OUTOFMEMORY, attrRun);
TextAttributeRun* pCurrentRun = attrRun.get();
pCurrentRun->SetAttributes(rgAttrs[0]);
pCurrentRun->SetLength(1);
for (size_t i = 1; i < cRowLength; i++)
{
if (pCurrentRun->GetAttributes() == rgAttrs[i])
{
TextAttributeRun* pCurrentRun = attrRun.get();
pCurrentRun->SetAttributes(rgAttrs[0]);
pCurrentRun->SetLength(pCurrentRun->GetLength() + 1);
}
else
{
pCurrentRun++;
pCurrentRun->SetAttributes(rgAttrs[i]);
pCurrentRun->SetLength(1);
for (size_t i = 1; i < cRowLength; i++)
{
if (pCurrentRun->GetAttributes() == rgAttrs[i])
{
pCurrentRun->SetLength(pCurrentRun->GetLength() + 1);
}
else
{
pCurrentRun++;
pCurrentRun->SetAttributes(rgAttrs[i]);
pCurrentRun->SetLength(1);
}
}
attrRun.swap(outAttrRun);
*cOutAttrRun = cDeltas;
}
}
attrRun.swap(outAttrRun);
*cOutAttrRun = cDeltas;
return HRESULT_FROM_NT(status);
return S_OK;
}
NoThrowString LogRunElement(_In_ TextAttributeRun& run)
@@ -725,10 +710,6 @@ class AttrRowTests
TEST_METHOD(TestResize)
{
CommonState state;
state.PrepareGlobalFont();
state.PrepareGlobalScreenBuffer();
pSingle->Resize(240);
pChain->Resize(240);
@@ -746,8 +727,5 @@ class AttrRowTests
VERIFY_THROWS_SPECIFIC(pSingle->Resize(0), wil::ResultException, [](wil::ResultException& e) { return e.GetErrorCode() == E_INVALIDARG; });
VERIFY_THROWS_SPECIFIC(pChain->Resize(0), wil::ResultException, [](wil::ResultException& e) { return e.GetErrorCode() == E_INVALIDARG; });
state.CleanupGlobalScreenBuffer();
state.CleanupGlobalFont();
}
};

View File

@@ -743,7 +743,7 @@ class ReflowTests
auto& row{ buffer->GetRowByOffset(i) };
auto& charRow{ row.GetCharRow() };
charRow.SetWrapForced(testRow.wrap);
row.SetWrapForced(testRow.wrap);
size_t j{};
for (auto it{ charRow.begin() }; it != charRow.end(); ++it)
@@ -792,7 +792,7 @@ class ReflowTests
const auto& charRow{ row.GetCharRow() };
indexString.Format(L"[Row %d]", i);
VERIFY_ARE_EQUAL(testRow.wrap, charRow.WasWrapForced(), indexString);
VERIFY_ARE_EQUAL(testRow.wrap, row.WasWrapForced(), indexString);
size_t j{};
for (auto it{ charRow.begin() }; it != charRow.end(); ++it)

View File

@@ -10,6 +10,7 @@
</PropertyGroup>
<Import Project="$(SolutionDir)src\common.build.pre.props" />
<ItemGroup>
<ClCompile Include="AttrRowTests.cpp" />
<ClCompile Include="ReflowTests.cpp" />
<ClCompile Include="TextColorTests.cpp" />
<ClCompile Include="TextAttributeTests.cpp" />
@@ -19,9 +20,9 @@
</ClCompile>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\types\lib\types.vcxproj">
<Project>{18d09a24-8240-42d6-8cb6-236eee820263}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\types\lib\types.vcxproj">
<Project>{18d09a24-8240-42d6-8cb6-236eee820263}</Project>
</ProjectReference>
<ProjectReference Include="..\lib\bufferout.vcxproj">
<Project>{0cf235bd-2da0-407e-90ee-c467e8bbc714}</Project>
</ProjectReference>

View File

@@ -14,6 +14,7 @@ DLLDEF =
SOURCES = \
$(SOURCES) \
AttrRowTests.cpp \
ReflowTests.cpp \
TextColorTests.cpp \
TextAttributeTests.cpp \
@@ -21,6 +22,7 @@ SOURCES = \
TARGETLIBS = \
$(CONSOLE_OBJ_PATH)\buffer\out\lib\$(O)\ConBufferOut.lib \
$(CONSOLE_OBJ_PATH)\types\lib\$(O)\ConTypes.lib \
$(TARGETLIBS) \
# -------------------------------------

View File

@@ -3,8 +3,7 @@
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
<Import Project="$(OpenConsoleDir)src\wap-common.build.pre.props" />
<PropertyGroup Label="Configuration">
<!-- This is necessary so the build system doesn't think we're a .NET project... -->
<TargetRuntime>Native</TargetRuntime>
<TargetPlatformVersion>10.0.18362.0</TargetPlatformVersion>
<TargetPlatformMinVersion>10.0.18362.0</TargetPlatformMinVersion>
<!--
@@ -17,6 +16,10 @@
<AppxOSMaxVersionTestedReplaceManifestVersion>false</AppxOSMaxVersionTestedReplaceManifestVersion>
<OCExecutionAliasName Condition="'$(WindowsTerminalBranding)'==''">wtd</OCExecutionAliasName>
<OCExecutionAliasName Condition="'$(OCExecutionAliasName)'==''">wt</OCExecutionAliasName>
<!-- VS 16.8 causes WAP projects to accidentally package System.Core.dll (from the CLR).
This has been fixed in VS 16.9 using the property below. It's safe for us to include
it here, even after 16.9 comes out. -->
<AddAdditionalExplicitAssemblyReferences>false</AddAdditionalExplicitAssemblyReferences>
</PropertyGroup>
<PropertyGroup>
<ProjectGuid>CA5CAD1A-224A-4171-B13A-F16E576FDD12</ProjectGuid>

View File

@@ -1,119 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="Globals">
<ProjectGuid>{2658e9b0-bd84-48b7-bb5e-3d18f4df07ba}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>Microsoft.Terminal.CommandlineArgs</RootNamespace>
<ProjectName>CommandlineArgs</ProjectName>
<TargetName>CommandlineArgs</TargetName>
<WindowsTargetPlatformMinVersion>10.0.17763.0</WindowsTargetPlatformMinVersion>
<ConfigurationType>StaticLibrary</ConfigurationType>
<SubSystem>Console</SubSystem>
<OpenConsoleUniversalApp>true</OpenConsoleUniversalApp>
</PropertyGroup>
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
<ItemDefinitionGroup>
<ClCompile>
<!-- For CLI11: It uses dynamic_cast to cast types around, which depends
on being compiled with RTTI (/GR). -->
<RuntimeTypeInfo>true</RuntimeTypeInfo>
</ClCompile>
</ItemDefinitionGroup>
<!-- ========================= Headers ======================== -->
<ItemGroup>
<ClInclude Include="AppCommandlineArgs.h" />
<ClInclude Include="Commandline.h" />
<ClInclude Include="pch.h" />
</ItemGroup>
<!-- ========================= Cpp Files ======================== -->
<ItemGroup>
<ClCompile Include="AppCommandlineArgs.cpp" />
<ClCompile Include="Commandline.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<!-- ========================= idl Files ======================== -->
<ItemGroup>
</ItemGroup>
<!-- ========================= Misc Files ======================== -->
<ItemGroup>
<OCResourceDirectory Include="Resources" />
<None Include="packages.config" />
</ItemGroup>
<!-- ========================= Project References ======================== -->
<ItemGroup>
<!--
the packaging project won't recurse through our dependencies, you have to
make sure that if you add a cppwinrt dependency to any of these projects,
you also update all the consumers
-->
<ProjectReference Include="$(OpenConsoleDir)src\types\lib\types.vcxproj" />
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\WinRTUtils\WinRTUtils.vcxproj">
<Project>{CA5CAD1A-039A-4929-BA2A-8BEB2E4106FE}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
<!-- For whatever reason, we can't include the TerminalControl and
TerminalSettings projects' winmds via project references. So we'll have to
manually include the winmds as References below -->
</ItemGroup>
<PropertyGroup>
<!-- This is a hack to get the ARM64 CI build working. See
https://github.com/Microsoft/msbuild/issues/3746 - it looks like MsBuild
just has a bug in it.-->
<ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>Warning</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
</PropertyGroup>
<ItemGroup>
<!-- Manually add references to each of our dependent winmds. Mark them as
private=false and CopyLocalSatelliteAssemblies=false, so that we don't
propagate them upwards (which can make referencing this project result in
duplicate type definitions)-->
<!-- Despite this lib only _really_ depending on the settings model, we need
to reference Connection, Control, and MUX here, because they have types that
TSM depends on, and the midl compiler will be mad if it can't find them. -->
<Reference Include="Microsoft.Terminal.TerminalConnection">
<HintPath>$(OpenConsoleCommonOutDir)TerminalConnection\Microsoft.Terminal.TerminalConnection.winmd</HintPath>
<IsWinMDFile>true</IsWinMDFile>
<Private>false</Private>
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
</Reference>
<Reference Include="Microsoft.Terminal.TerminalControl">
<HintPath>$(OpenConsoleCommonOutDir)TerminalControl\Microsoft.Terminal.TerminalControl.winmd</HintPath>
<IsWinMDFile>true</IsWinMDFile>
<Private>false</Private>
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
</Reference>
<Reference Include="Microsoft.Terminal.Settings.Model">
<HintPath>$(OpenConsoleCommonOutDir)Microsoft.Terminal.Settings.Model\Microsoft.Terminal.Settings.Model.winmd</HintPath>
<IsWinMDFile>true</IsWinMDFile>
<Private>false</Private>
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
</Reference>
</ItemGroup>
<!-- ====================== Compiler & Linker Flags ===================== -->
<ItemDefinitionGroup>
<ClCompile>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<AdditionalIncludeDirectories>..;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
<!-- Manually disable unreachable code warning, because jconcpp has a ton of that. -->
<DisableSpecificWarnings>4702;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalDependencies>WindowsApp.lib;shell32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<!-- ========================= Globals ======================== -->
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets'))" />
</Target>
</Project>

View File

@@ -1,198 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="CmdCommandArgDesc" xml:space="preserve">
<value>An optional command, with arguments, to be spawned in the new tab or pane</value>
</data>
<data name="CmdFocusTabDesc" xml:space="preserve">
<value>Move focus to another tab</value>
</data>
<data name="CmdFocusTabNextArgDesc" xml:space="preserve">
<value>Move focus to the next tab</value>
</data>
<data name="CmdFTDesc" xml:space="preserve">
<value>An alias for the "focus-tab" subcommand.</value>
<comment>{Locked="\"focus-tab\""}</comment>
</data>
<data name="CmdFocusTabPrevArgDesc" xml:space="preserve">
<value>Move focus to the previous tab</value>
</data>
<data name="CmdFocusTabTargetArgDesc" xml:space="preserve">
<value>Move focus the tab at the given index</value>
</data>
<data name="CmdSplitPaneSizeArgDesc" xml:space="preserve">
<value>Specify the size as a percentage of the parent pane. Valid values are between (0,1), exclusive.</value>
</data>
<data name="CmdNewTabDesc" xml:space="preserve">
<value>Create a new tab</value>
</data>
<data name="CmdNTDesc" xml:space="preserve">
<value>An alias for the "new-tab" subcommand.</value>
<comment>{Locked="\"new-tab\""}</comment>
</data>
<data name="CmdProfileArgDesc" xml:space="preserve">
<value>Open with the given profile. Accepts either the name or GUID of a profile</value>
</data>
<data name="CmdSplitPaneDesc" xml:space="preserve">
<value>Create a new split pane</value>
</data>
<data name="CmdSPDesc" xml:space="preserve">
<value>An alias for the "split-pane" subcommand.</value>
<comment>{Locked="\"split-pane\""}</comment>
</data>
<data name="CmdSplitPaneHorizontalArgDesc" xml:space="preserve">
<value>Create the new pane as a horizontal split (think [-])</value>
</data>
<data name="CmdSplitPaneVerticalArgDesc" xml:space="preserve">
<value>Create the new pane as a vertical split (think [|])</value>
</data>
<data name="CmdStartingDirArgDesc" xml:space="preserve">
<value>Open in the given directory instead of the profile's set "startingDirectory"</value>
<comment>{Locked="\"startingDirectory\""}</comment>
</data>
<data name="CmdTitleArgDesc" xml:space="preserve">
<value>Open the terminal with the provided title instead of the profile's set "title"</value>
<comment>{Locked="\"title\""}</comment>
</data>
<data name="CmdTabColorArgDesc" xml:space="preserve">
<value>Open the tab with the specified color, in #rrggbb format</value>
</data>
<data name="CmdVersionDesc" xml:space="preserve">
<value>Display the application version</value>
</data>
<data name="CmdMaximizedDesc" xml:space="preserve">
<value>Launch the window maximized</value>
</data>
<data name="CmdFullscreenDesc" xml:space="preserve">
<value>Launch the window in fullscreen mode</value>
</data>
<data name="CmdMoveFocusDesc" xml:space="preserve">
<value>Move focus to the adjacent pane in the specified direction</value>
</data>
<data name="CmdMFDesc" xml:space="preserve">
<value>An alias for the "move-focus" subcommand.</value>
<comment>{Locked="\"move-focus\""}</comment>
</data>
<data name="CmdMoveFocusDirectionArgDesc" xml:space="preserve">
<value>The direction to move focus in</value>
</data>
<data name="CmdFocusDesc" xml:space="preserve">
<value>Launch the window in focus mode</value>
</data>
</root>

View File

@@ -1,4 +0,0 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"

View File

@@ -1,51 +0,0 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
//
// pch.h
// Header for platform projection include files
//
#pragma once
#define WIN32_LEAN_AND_MEAN
#define NOMCX
#define NOHELP
#define NOCOMM
// Manually include til after we include Windows.Foundation to give it winrt superpowers
#define BLOCK_TIL
#include <LibraryIncludes.h>
// This is inexplicable, but for whatever reason, cppwinrt conflicts with the
// SDK definition of this function, so the only fix is to undef it.
// from WinBase.h
// Windows::UI::Xaml::Media::Animation::IStoryboard::GetCurrentTime
#ifdef GetCurrentTime
#undef GetCurrentTime
#endif
#include <wil/cppwinrt.h>
#include <unknwn.h>
#include <hstring.h>
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Foundation.Collections.h>
// You might think "we're not doing any UI in this lib", and you'd be right.
// However, we need this for Windows.UI.Color
#include <winrt/windows.ui.h>
// Including TraceLogging essentials for the binary
#include <TraceLoggingProvider.h>
#include <winmeta.h>
TRACELOGGING_DECLARE_PROVIDER(g_hTerminalAppProvider);
#include <telemetry/ProjectTelemetry.h>
#include <TraceLoggingActivity.h>
#include <shellapi.h>
#include <shobjidl_core.h>
#include <winrt/Microsoft.Terminal.Settings.Model.h>
// Manually include til after we include Windows.Foundation to give it winrt superpowers
#include "til.h"

View File

@@ -35,6 +35,7 @@ namespace SettingsModelLocalTests
TEST_METHOD(CanLayerColorScheme);
TEST_METHOD(LayerColorSchemeProperties);
TEST_METHOD(LayerColorSchemesOnArray);
TEST_METHOD(UpdateSchemeReferences);
TEST_CLASS_SETUP(ClassSetup)
{
@@ -290,4 +291,81 @@ namespace SettingsModelLocalTests
VERIFY_ARE_EQUAL(ARGB(0, 7, 7, 7), scheme2->_Background);
}
}
void ColorSchemeTests::UpdateSchemeReferences()
{
const std::string settingsString{ R"json({
"defaultProfile": "Inherited reference",
"profiles": {
"defaults": {
"colorScheme": "Scheme 1"
},
"list": [
{
"name": "Explicit scheme reference",
"colorScheme": "Scheme 1"
},
{
"name": "Explicit reference; hidden",
"colorScheme": "Scheme 1",
"hidden": true
},
{
"name": "Inherited reference"
},
{
"name": "Different reference",
"colorScheme": "Scheme 2"
}
]
},
"schemes": [
{ "name": "Scheme 1" },
{ "name": "Scheme 2" },
{ "name": "Scheme 1 (renamed)" }
]
})json" };
auto settings{ winrt::make_self<CascadiaSettings>(false) };
settings->_ParseJsonString(settingsString, false);
settings->_ApplyDefaultsFromUserSettings();
settings->LayerJson(settings->_userSettings);
settings->_ValidateSettings();
// update all references to "Scheme 1"
const auto newName{ L"Scheme 1 (renamed)" };
settings->UpdateColorSchemeReferences(L"Scheme 1", newName);
// verify profile defaults
Log::Comment(L"Profile Defaults");
VERIFY_ARE_EQUAL(newName, settings->ProfileDefaults().ColorSchemeName());
VERIFY_IS_TRUE(settings->ProfileDefaults().HasColorSchemeName());
// verify all other profiles
const auto& profiles{ settings->AllProfiles() };
{
const auto& prof{ profiles.GetAt(0) };
Log::Comment(prof.Name().c_str());
VERIFY_ARE_EQUAL(newName, prof.ColorSchemeName());
VERIFY_IS_TRUE(prof.HasColorSchemeName());
}
{
const auto& prof{ profiles.GetAt(1) };
Log::Comment(prof.Name().c_str());
VERIFY_ARE_EQUAL(newName, prof.ColorSchemeName());
VERIFY_IS_TRUE(prof.HasColorSchemeName());
}
{
const auto& prof{ profiles.GetAt(2) };
Log::Comment(prof.Name().c_str());
VERIFY_ARE_EQUAL(newName, prof.ColorSchemeName());
VERIFY_IS_FALSE(prof.HasColorSchemeName());
}
{
const auto& prof{ profiles.GetAt(3) };
Log::Comment(prof.Name().c_str());
VERIFY_ARE_EQUAL(L"Scheme 2", prof.ColorSchemeName());
VERIFY_IS_TRUE(prof.HasColorSchemeName());
}
}
}

View File

@@ -79,6 +79,7 @@ namespace SettingsModelLocalTests
TEST_METHOD(TestCommandsAndKeybindings);
TEST_METHOD(TestNestedCommandWithoutName);
TEST_METHOD(TestNestedCommandWithBadSubCommands);
TEST_METHOD(TestUnbindNestedCommand);
TEST_METHOD(TestRebindNestedCommand);
@@ -1376,7 +1377,7 @@ namespace SettingsModelLocalTests
},
{
"name": "parent",
"commands": [
"commands": [
{ "command": { "action": "setColorScheme", "colorScheme": "invalidScheme" } }
]
}
@@ -1403,11 +1404,11 @@ namespace SettingsModelLocalTests
},
{
"name": "grandparent",
"commands": [
"commands": [
{
"name": "parent",
"commands": [
{
{
"command": { "action": "setColorScheme", "colorScheme": "invalidScheme" }
}
]
@@ -1909,7 +1910,8 @@ namespace SettingsModelLocalTests
"keybindings": [
{ "command": { "action": "splitPane", "split":"auto" }, "keys": [ "ctrl+alt+t", "ctrl+a" ] },
{ "command": { "action": "moveFocus" }, "keys": [ "ctrl+a" ] },
{ "command": { "action": "resizePane" }, "keys": [ "ctrl+b" ] }
{ "command": { "action": "resizePane" }, "keys": [ "ctrl+b" ] },
{ "name": "invalid nested", "commands":[ { "name" : "hello" }, { "name" : "world" } ] }
]
})" };
@@ -1918,18 +1920,20 @@ namespace SettingsModelLocalTests
VERIFY_ARE_EQUAL(0u, settings->_globals->_keymap->_keyShortcuts.size());
VERIFY_ARE_EQUAL(3u, settings->_globals->_keybindingsWarnings.size());
VERIFY_ARE_EQUAL(4u, settings->_globals->_keybindingsWarnings.size());
VERIFY_ARE_EQUAL(SettingsLoadWarnings::TooManyKeysForChord, settings->_globals->_keybindingsWarnings.at(0));
VERIFY_ARE_EQUAL(SettingsLoadWarnings::MissingRequiredParameter, settings->_globals->_keybindingsWarnings.at(1));
VERIFY_ARE_EQUAL(SettingsLoadWarnings::MissingRequiredParameter, settings->_globals->_keybindingsWarnings.at(2));
VERIFY_ARE_EQUAL(SettingsLoadWarnings::FailedToParseSubCommands, settings->_globals->_keybindingsWarnings.at(3));
settings->_ValidateKeybindings();
VERIFY_ARE_EQUAL(4u, settings->_warnings.Size());
VERIFY_ARE_EQUAL(5u, settings->_warnings.Size());
VERIFY_ARE_EQUAL(SettingsLoadWarnings::AtLeastOneKeybindingWarning, settings->_warnings.GetAt(0));
VERIFY_ARE_EQUAL(SettingsLoadWarnings::TooManyKeysForChord, settings->_warnings.GetAt(1));
VERIFY_ARE_EQUAL(SettingsLoadWarnings::MissingRequiredParameter, settings->_warnings.GetAt(2));
VERIFY_ARE_EQUAL(SettingsLoadWarnings::MissingRequiredParameter, settings->_warnings.GetAt(3));
VERIFY_ARE_EQUAL(SettingsLoadWarnings::FailedToParseSubCommands, settings->_warnings.GetAt(4));
}
void DeserializationTests::ValidateExecuteCommandlineWarning()
@@ -2316,6 +2320,53 @@ namespace SettingsModelLocalTests
VERIFY_ARE_EQUAL(0u, commands.Size());
}
void DeserializationTests::TestNestedCommandWithBadSubCommands()
{
// This test tests a nested command without a name specified. This type
// of command should just be ignored, since we can't auto-generate names
// for nested commands, they _must_ have names specified.
const std::string settingsJson{ R"(
{
"defaultProfile": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
"profiles": [
{
"name": "profile0",
"guid": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
"historySize": 1,
"commandline": "cmd.exe"
}
],
"actions": [
{
"name": "nested command",
"commands": [
{
"name": "child1"
},
{
"name": "child2"
}
]
},
],
"schemes": [ { "name": "Campbell" } ] // This is included here to prevent settings validation errors.
})" };
VerifyParseSucceeded(settingsJson);
auto settings = winrt::make_self<implementation::CascadiaSettings>();
settings->_ParseJsonString(settingsJson, false);
settings->LayerJson(settings->_userSettings);
auto commands = settings->_globals->Commands();
settings->_ValidateSettings();
VERIFY_ARE_EQUAL(2u, settings->_warnings.Size());
VERIFY_ARE_EQUAL(SettingsLoadWarnings::AtLeastOneKeybindingWarning, settings->_warnings.GetAt(0));
VERIFY_ARE_EQUAL(SettingsLoadWarnings::FailedToParseSubCommands, settings->_warnings.GetAt(1));
VERIFY_ARE_EQUAL(0u, commands.Size());
}
void DeserializationTests::TestUnbindNestedCommand()
{
// Test that layering a command with `"commands": null` set will unbind a command that already exists.

View File

@@ -226,6 +226,7 @@ namespace SettingsModelLocalTests
const std::string settingsString{ R"({
"$schema": "https://aka.ms/terminal-profiles-schema",
"defaultProfile": "{61c54bbd-1111-5271-96e7-009a87ff44bf}",
"disabledProfileSources": [ "Windows.Terminal.Wsl" ],
"profiles": {
"defaults": {

View File

@@ -6,7 +6,7 @@
#include "../types/inc/utils.hpp"
#include "../TerminalApp/TerminalPage.h"
#include "../CommandlineArgs/AppCommandlineArgs.h"
#include "../TerminalApp/AppCommandlineArgs.h"
using namespace WEX::Logging;
using namespace WEX::Common;
@@ -14,7 +14,7 @@ using namespace WEX::TestExecution;
using namespace winrt::Microsoft::Terminal::Settings::Model;
using namespace winrt::TerminalApp;
using namespace ::Microsoft::Terminal::CommandlineArgs;
using namespace ::TerminalApp;
namespace TerminalAppLocalTests
{

View File

@@ -12,7 +12,7 @@
#include "../CppWinrtTailored.h"
using namespace Microsoft::Console;
using namespace Microsoft::Terminal::CommandlineArgs;
using namespace TerminalApp;
using namespace winrt::TerminalApp;
using namespace winrt::Microsoft::Terminal::Settings::Model;

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Windows.CppWinRT" version="2.0.201017.1" targetFramework="native" />
<package id="Microsoft.Windows.CppWinRT" version="2.0.210309.3" targetFramework="native" />
</packages>

View File

@@ -266,7 +266,16 @@ std::wstring OpenTerminalHere::_GetPathFromExplorer() const
return path;
}
auto shell = create_instance<IShellWindows>(CLSID_ShellWindows);
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;
@@ -285,6 +294,7 @@ std::wstring OpenTerminalHere::_GetPathFromExplorer() const
com_ptr<IWebBrowserApp> tmp;
if (FAILED(disp->QueryInterface(tmp.put())))
{
disp = nullptr; // get rid of DEBUG non-nullptr warning
continue;
}
@@ -293,8 +303,11 @@ std::wstring OpenTerminalHere::_GetPathFromExplorer() const
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)

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Windows.CppWinRT" version="2.0.201017.1" targetFramework="native" />
<package id="Microsoft.Windows.CppWinRT" version="2.0.210309.3" targetFramework="native" />
</packages>

View File

@@ -17,6 +17,7 @@ using namespace winrt::Microsoft::Terminal;
using namespace winrt::Microsoft::Terminal::Settings::Model;
using namespace winrt::Microsoft::Terminal::TerminalControl;
using namespace winrt::Microsoft::Terminal::TerminalConnection;
using namespace ::TerminalApp;
namespace winrt
{

View File

@@ -2,12 +2,14 @@
// Licensed under the MIT license.
#include "pch.h"
#include "AppLogic.h"
#include "AppCommandlineArgs.h"
#include "../types/inc/utils.hpp"
#include <LibraryResources.h>
using namespace winrt::TerminalApp;
using namespace winrt::Microsoft::Terminal::Settings::Model;
using namespace Microsoft::Terminal::CommandlineArgs;
using namespace TerminalApp;
// Either a ; at the start of a line, or a ; preceded by any non-\ char.
const std::wregex AppCommandlineArgs::_commandDelimiterRegex{ LR"(^;|[^\\];)" };
@@ -742,7 +744,7 @@ std::optional<winrt::Microsoft::Terminal::Settings::Model::LaunchMode> AppComman
// - 0 if the commandline was successfully parsed
int AppCommandlineArgs::ParseArgs(winrt::array_view<const winrt::hstring>& args)
{
auto commands = ::Microsoft::Terminal::CommandlineArgs::AppCommandlineArgs::BuildCommands(args);
auto commands = ::TerminalApp::AppCommandlineArgs::BuildCommands(args);
for (auto& cmdBlob : commands)
{

View File

@@ -2,7 +2,6 @@
// Licensed under the MIT license.
#pragma once
#include <CLI11/CLI11.hpp>
#include "Commandline.h"
#ifdef UNIT_TESTING
@@ -13,12 +12,12 @@ namespace TerminalAppLocalTests
};
#endif
namespace Microsoft::Terminal::CommandlineArgs
namespace TerminalApp
{
class AppCommandlineArgs;
};
class Microsoft::Terminal::CommandlineArgs::AppCommandlineArgs final
class TerminalApp::AppCommandlineArgs final
{
public:
static constexpr std::string_view NixHelpFlag{ "-?" };

View File

@@ -17,7 +17,7 @@ using namespace winrt::Windows::System;
using namespace winrt::Microsoft::Terminal;
using namespace winrt::Microsoft::Terminal::TerminalControl;
using namespace winrt::Microsoft::Terminal::Settings::Model;
using namespace ::Microsoft::Terminal::CommandlineArgs;
using namespace ::TerminalApp;
namespace winrt
{
@@ -44,7 +44,8 @@ static const std::array<std::wstring_view, static_cast<uint32_t>(SettingsLoadWar
USES_RESOURCE(L"FailedToWriteToSettings"),
USES_RESOURCE(L"InvalidColorSchemeInCmd"),
USES_RESOURCE(L"InvalidSplitSize"),
USES_RESOURCE(L"FailedToParseStartupActions")
USES_RESOURCE(L"FailedToParseStartupActions"),
USES_RESOURCE(L"FailedToParseSubCommands"),
};
static const std::array<std::wstring_view, static_cast<uint32_t>(SettingsLoadErrors::ERRORS_SIZE)> settingsLoadErrorsLabels {
USES_RESOURCE(L"NoProfilesText"),
@@ -841,7 +842,8 @@ namespace winrt::TerminalApp::implementation
// editors, who will write a temp file, then rename it to be the
// actual file you wrote. So listen for that too.
if (!(event == wil::FolderChangeEvent::Modified ||
event == wil::FolderChangeEvent::RenameNewName))
event == wil::FolderChangeEvent::RenameNewName ||
event == wil::FolderChangeEvent::Removed))
{
return;
}
@@ -1152,7 +1154,7 @@ namespace winrt::TerminalApp::implementation
int32_t AppLogic::ExecuteCommandline(array_view<const winrt::hstring> args)
{
::Microsoft::Terminal::CommandlineArgs::AppCommandlineArgs appArgs;
::TerminalApp::AppCommandlineArgs appArgs;
auto result = appArgs.ParseArgs(args);
if (result == 0)
{

View File

@@ -85,8 +85,8 @@ namespace winrt::TerminalApp::implementation
std::atomic<bool> _settingsReloadQueued{ false };
::Microsoft::Terminal::CommandlineArgs::AppCommandlineArgs _appArgs;
::Microsoft::Terminal::CommandlineArgs::AppCommandlineArgs _settingsAppArgs;
::TerminalApp::AppCommandlineArgs _appArgs;
::TerminalApp::AppCommandlineArgs _settingsAppArgs;
int _ParseArgs(winrt::array_view<const hstring>& args);
void _ShowLoadErrorsDialog(const winrt::hstring& titleKey, const winrt::hstring& contentKey, HRESULT settingsLoadedResult);

View File

@@ -12,7 +12,7 @@
</Style>
</Flyout.FlyoutPresenterStyle>
<StackPanel Orientation="Horizontal">
<StackPanel>
<StackPanel XYFocusKeyboardNavigation="Enabled">
<VariableSizedWrapGrid Orientation="Horizontal" MaximumRowsOrColumns="4" HorizontalAlignment="Center" Margin="0, 3, 0, 0">
<VariableSizedWrapGrid.Resources>
<Style TargetType="Rectangle">

View File

@@ -243,6 +243,9 @@ namespace winrt::TerminalApp::implementation
Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e)
{
auto key = e.OriginalKey();
auto const ctrlDown = WI_IsFlagSet(CoreWindow::GetForCurrentThread().GetKeyState(winrt::Windows::System::VirtualKey::Control), CoreVirtualKeyStates::Down);
auto const altDown = WI_IsFlagSet(CoreWindow::GetForCurrentThread().GetKeyState(winrt::Windows::System::VirtualKey::Menu), CoreVirtualKeyStates::Down);
auto const shiftDown = WI_IsFlagSet(CoreWindow::GetForCurrentThread().GetKeyState(winrt::Windows::System::VirtualKey::Shift), CoreVirtualKeyStates::Down);
// Some keypresses such as Tab, Return, Esc, and Arrow Keys are ignored by controls because
// they're not considered input key presses. While they don't raise KeyDown events,
@@ -253,10 +256,6 @@ namespace winrt::TerminalApp::implementation
// a really widely used keyboard navigation key.
if (_currentMode == CommandPaletteMode::TabSwitchMode && _keymap)
{
auto const ctrlDown = WI_IsFlagSet(CoreWindow::GetForCurrentThread().GetKeyState(winrt::Windows::System::VirtualKey::Control), CoreVirtualKeyStates::Down);
auto const altDown = WI_IsFlagSet(CoreWindow::GetForCurrentThread().GetKeyState(winrt::Windows::System::VirtualKey::Menu), CoreVirtualKeyStates::Down);
auto const shiftDown = WI_IsFlagSet(CoreWindow::GetForCurrentThread().GetKeyState(winrt::Windows::System::VirtualKey::Shift), CoreVirtualKeyStates::Down);
winrt::Microsoft::Terminal::TerminalControl::KeyChord kc{ ctrlDown, altDown, shiftDown, static_cast<int32_t>(key) };
const auto action = _keymap.TryLookup(kc);
if (action)
@@ -265,48 +264,28 @@ namespace winrt::TerminalApp::implementation
{
SelectNextItem(false);
e.Handled(true);
return;
}
else if (action.Action() == ShortcutAction::NextTab)
{
SelectNextItem(true);
e.Handled(true);
return;
}
}
}
else if (key == VirtualKey::Home)
{
auto const state = CoreWindow::GetForCurrentThread().GetKeyState(winrt::Windows::System::VirtualKey::Control);
if (WI_IsFlagSet(state, CoreVirtualKeyStates::Down))
{
ScrollToTop();
e.Handled(true);
}
}
else if (key == VirtualKey::End)
{
auto const state = CoreWindow::GetForCurrentThread().GetKeyState(winrt::Windows::System::VirtualKey::Control);
if (WI_IsFlagSet(state, CoreVirtualKeyStates::Down))
{
ScrollToBottom();
e.Handled(true);
}
}
}
// Method Description:
// - Process keystrokes in the input box. This is used for moving focus up
// and down the list of commands in Action mode, and for executing
// commands in both Action mode and Commandline mode.
// Arguments:
// - e: the KeyRoutedEventArgs containing info about the keystroke.
// Return Value:
// - <none>
void CommandPalette::_keyDownHandler(IInspectable const& /*sender*/,
Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e)
{
auto key = e.OriginalKey();
if (key == VirtualKey::Up)
if (key == VirtualKey::Home && ctrlDown)
{
ScrollToTop();
e.Handled(true);
}
else if (key == VirtualKey::End && ctrlDown)
{
ScrollToBottom();
e.Handled(true);
}
else if (key == VirtualKey::Up)
{
// Action Mode: Move focus to the next item in the list.
SelectNextItem(false);
@@ -352,16 +331,22 @@ namespace winrt::TerminalApp::implementation
e.Handled(true);
}
else if (key == VirtualKey::Back)
else if (key == VirtualKey::Back && _searchBox().Text().empty() && _lastFilterTextWasEmpty && _currentMode == CommandPaletteMode::ActionMode)
{
// If the last filter text was empty, and we're backspacing from
// that state, then the user "backspaced" the virtual '>' we're
// using as the action mode indicator. Switch into commandline mode.
if (_searchBox().Text().empty() && _lastFilterTextWasEmpty && _currentMode == CommandPaletteMode::ActionMode)
{
_switchToMode(CommandPaletteMode::CommandlineMode);
}
_switchToMode(CommandPaletteMode::CommandlineMode);
e.Handled(true);
}
else if (key == VirtualKey::C && ctrlDown)
{
_searchBox().CopySelectionToClipboard();
e.Handled(true);
}
else if (key == VirtualKey::V && ctrlDown)
{
_searchBox().PasteFromClipboard();
e.Handled(true);
}
}
@@ -451,6 +436,12 @@ namespace winrt::TerminalApp::implementation
void CommandPalette::_lostFocusHandler(Windows::Foundation::IInspectable const& /*sender*/,
Windows::UI::Xaml::RoutedEventArgs const& /*args*/)
{
const auto flyout = _searchBox().ContextFlyout();
if (flyout && flyout.IsOpen())
{
return;
}
auto focusedElementOrAncestor = Input::FocusManager::GetFocusedElement(this->XamlRoot()).try_as<DependencyObject>();
while (focusedElementOrAncestor)
{

View File

@@ -5,7 +5,7 @@
#include "FilteredCommand.h"
#include "CommandPalette.g.h"
#include "../CommandlineArgs/AppCommandlineArgs.h"
#include "AppCommandlineArgs.h"
#include "../../cascadia/inc/cppwinrt_utils.h"
// fwdecl unittest classes
@@ -75,8 +75,7 @@ namespace winrt::TerminalApp::implementation
Windows::UI::Xaml::RoutedEventArgs const& args);
void _previewKeyDownHandler(Windows::Foundation::IInspectable const& sender,
Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e);
void _keyDownHandler(Windows::Foundation::IInspectable const& sender,
Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e);
void _keyUpHandler(Windows::Foundation::IInspectable const& sender,
Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e);
@@ -132,7 +131,7 @@ namespace winrt::TerminalApp::implementation
static constexpr int CommandLineHistoryLength = 10;
Windows::Foundation::Collections::IVector<winrt::TerminalApp::FilteredCommand> _commandLineHistory{ nullptr };
::Microsoft::Terminal::CommandlineArgs::AppCommandlineArgs _appArgs;
::TerminalApp::AppCommandlineArgs _appArgs;
friend class TerminalAppLocalTests::TabTests;
};

View File

@@ -16,7 +16,6 @@ the MIT License. See LICENSE in the project root for license information. -->
AllowFocusOnInteraction="True"
PointerPressed="_rootPointerPressed"
PreviewKeyDown="_previewKeyDownHandler"
KeyDown="_keyDownHandler"
PreviewKeyUp="_keyUpHandler"
LostFocus="_lostFocusHandler"
mc:Ignorable="d"
@@ -34,6 +33,7 @@ the MIT License. See LICENSE in the project root for license information. -->
<local:EmptyStringVisibilityConverter x:Key="ParsedCommandLineTextVisibilityConverter"/>
<local:EmptyStringVisibilityConverter x:Key="ParentCommandVisibilityConverter"/>
<local:HasNestedCommandsVisibilityConverter x:Key="HasNestedCommandsVisibilityConverter"/>
<local:HasNestedCommandsHelpTextConverter x:Key="HasNestedCommandsHelpTextConverter"/>
<model:IconPathConverter x:Key="IconSourceConverter"/>
<ResourceDictionary.ThemeDictionaries>
@@ -132,7 +132,7 @@ the MIT License. See LICENSE in the project root for license information. -->
<Style x:Key="KeyChordTextBlockStyle" TargetType="TextBlock"/>
<!-- ParsedCommandLineText styles (use XAML defaults for High Contrast theme) -->
<Style x:Key="ParsedCommandLineBoderStyle" TargetType="Border"/>
<Style x:Key="ParsedCommandLineBorderStyle" TargetType="Border"/>
<Style x:Key="ParsedCommandLineTextBlockStyle" TargetType="TextBlock"/>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
@@ -278,7 +278,6 @@ the MIT License. See LICENSE in the project root for license information. -->
AllowDrop="False"
IsItemClickEnabled="True"
ItemClick="_listItemClicked"
PreviewKeyDown="_keyDownHandler"
ItemsSource="{x:Bind FilteredActions}">
<ItemsControl.ItemTemplate >
@@ -287,9 +286,9 @@ the MIT License. See LICENSE in the project root for license information. -->
<!-- This HorizontalContentAlignment="Stretch" is important
to make sure it takes the entire width of the line -->
<ListViewItem HorizontalContentAlignment="Stretch"
IsTabStop="False"
AutomationProperties.Name="{x:Bind Item.Name, Mode=OneWay}"
AutomationProperties.AcceleratorKey="{x:Bind Item.KeyChordText, Mode=OneWay}">
AutomationProperties.AcceleratorKey="{x:Bind Item.KeyChordText, Mode=OneWay}"
AutomationProperties.HelpText="{x:Bind Item, Mode=OneWay, Converter={StaticResource HasNestedCommandsHelpTextConverter}}">
<Grid HorizontalAlignment="Stretch" ColumnSpacing="8" >
<Grid.ColumnDefinitions>
@@ -314,7 +313,13 @@ the MIT License. See LICENSE in the project root for license information. -->
<!-- The block for the key chord is only visible
when there's actual text set as the label. See
CommandKeyChordVisibilityConverter for details. -->
CommandKeyChordVisibilityConverter for details.
We're setting the accessibility view on the
border and text block to Raw because otherwise,
Narrator will read out the key chord. Problem is,
it already did that because it was the list item's
"AcceleratorKey". It's redundant. -->
<Border
Grid.Column="2"
Visibility="{x:Bind Item.KeyChordText,
@@ -323,12 +328,14 @@ the MIT License. See LICENSE in the project root for license information. -->
Style="{ThemeResource KeyChordBorderStyle}"
Padding="2,0,2,0"
HorizontalAlignment="Right"
VerticalAlignment="Center">
VerticalAlignment="Center"
AutomationProperties.AccessibilityView="Raw">
<TextBlock
Style="{ThemeResource KeyChordTextBlockStyle}"
FontSize="12"
Text="{x:Bind Item.KeyChordText, Mode=OneWay}" />
Text="{x:Bind Item.KeyChordText, Mode=OneWay}"
AutomationProperties.AccessibilityView="Raw" />
</Border>
<!-- xE70E is ChevronUp. Rotated 90 degrees, it's _ChevronRight_ -->

View File

@@ -4,7 +4,7 @@
#include "pch.h"
#include "Commandline.h"
using namespace Microsoft::Terminal::CommandlineArgs;
using namespace TerminalApp;
size_t Commandline::Argc() const
{

View File

@@ -23,12 +23,12 @@ namespace TerminalAppLocalTests
{
class CommandlineTest;
};
namespace Microsoft::Terminal::CommandlineArgs
namespace TerminalApp
{
class Commandline;
};
class Microsoft::Terminal::CommandlineArgs::Commandline
class TerminalApp::Commandline
{
public:
static constexpr std::wstring_view Delimiter{ L";" };

View File

@@ -1,6 +1,9 @@
#include "pch.h"
#include "HasNestedCommandsVisibilityConverter.h"
#include "HasNestedCommandsVisibilityConverter.g.cpp"
#include "HasNestedCommandsHelpTextConverter.g.cpp"
#include "LibraryResources.h"
using namespace winrt::Windows;
using namespace winrt::Windows::UI::Xaml;
@@ -36,4 +39,23 @@ namespace winrt::TerminalApp::implementation
{
throw hresult_not_implemented();
}
Foundation::IInspectable HasNestedCommandsHelpTextConverter::Convert(Foundation::IInspectable const& value,
Windows::UI::Xaml::Interop::TypeName const& /* targetType */,
Foundation::IInspectable const& /* parameter */,
hstring const& /* language */)
{
const auto paletteItem{ value.try_as<winrt::TerminalApp::ActionPaletteItem>() };
const auto hasNestedCommands = paletteItem && paletteItem.Command().HasNestedCommands();
return winrt::box_value(hasNestedCommands ? RS_(L"CommandPalette_MoreOptions/[using:Windows.UI.Xaml.Automation]AutomationProperties/HelpText") : L"");
}
// unused for one-way bindings
Foundation::IInspectable HasNestedCommandsHelpTextConverter::ConvertBack(Foundation::IInspectable const& /* value */,
Windows::UI::Xaml::Interop::TypeName const& /* targetType */,
Foundation::IInspectable const& /* parameter */,
hstring const& /* language */)
{
throw hresult_not_implemented();
}
}

View File

@@ -1,6 +1,7 @@
#pragma once
#include "HasNestedCommandsVisibilityConverter.g.h"
#include "HasNestedCommandsHelpTextConverter.g.h"
#include "../inc/cppwinrt_utils.h"
namespace winrt::TerminalApp::implementation
@@ -19,9 +20,25 @@ namespace winrt::TerminalApp::implementation
Windows::Foundation::IInspectable const& parameter,
hstring const& language);
};
struct HasNestedCommandsHelpTextConverter : HasNestedCommandsHelpTextConverterT<HasNestedCommandsHelpTextConverter>
{
HasNestedCommandsHelpTextConverter() = default;
Windows::Foundation::IInspectable Convert(Windows::Foundation::IInspectable const& value,
Windows::UI::Xaml::Interop::TypeName const& targetType,
Windows::Foundation::IInspectable const& parameter,
hstring const& language);
Windows::Foundation::IInspectable ConvertBack(Windows::Foundation::IInspectable const& value,
Windows::UI::Xaml::Interop::TypeName const& targetType,
Windows::Foundation::IInspectable const& parameter,
hstring const& language);
};
}
namespace winrt::TerminalApp::factory_implementation
{
BASIC_FACTORY(HasNestedCommandsVisibilityConverter);
BASIC_FACTORY(HasNestedCommandsHelpTextConverter);
}

View File

@@ -16,4 +16,9 @@ namespace TerminalApp
HasNestedCommandsVisibilityConverter();
};
runtimeclass HasNestedCommandsHelpTextConverter : [default] Windows.UI.Xaml.Data.IValueConverter
{
HasNestedCommandsHelpTextConverter();
};
}

View File

@@ -10,6 +10,9 @@
#include "MinMaxCloseControl.h"
#include "MinMaxCloseControl.g.cpp"
#include <LibraryResources.h>
using namespace winrt::Windows::UI::Xaml;
namespace winrt::TerminalApp::implementation
@@ -77,6 +80,7 @@ namespace winrt::TerminalApp::implementation
MinimizeButton().Height(maximizedHeight);
MaximizeButton().Height(maximizedHeight);
CloseButton().Height(maximizedHeight);
MaximizeToolTip().Text(RS_(L"WindowRestoreDownButtonToolTip"));
break;
case WindowVisualState::WindowVisualStateNormal:
@@ -87,6 +91,7 @@ namespace winrt::TerminalApp::implementation
MinimizeButton().Height(windowedHeight);
MaximizeButton().Height(windowedHeight);
CloseButton().Height(windowedHeight);
MaximizeToolTip().Text(RS_(L"WindowMaximizeButtonToolTip"));
break;
}
}

View File

@@ -188,6 +188,13 @@ the MIT License. See LICENSE in the project root for license information. -->
<x:String x:Key="CaptionButtonPathWindowMaximized">M 0 2 h 8 v 8 h -8 v -8 M 2 2 v -2 h 8 v 8 h -2</x:String>
</ResourceDictionary>
</Button.Resources>
<ToolTipService.ToolTip>
<ToolTip>
<TextBlock>
<Run x:Name="MaximizeToolTip"/>
</TextBlock>
</ToolTip>
</ToolTipService.ToolTip>
</Button>
<Button Height="{StaticResource CaptionButtonHeightWindowed}" MinWidth="46.0" Width="46.0"
x:Name="CloseButton"

View File

@@ -17,6 +17,7 @@ using namespace winrt::Microsoft::Terminal::Settings::Model;
using namespace winrt::Microsoft::Terminal::TerminalControl;
using namespace winrt::Microsoft::Terminal::TerminalConnection;
using namespace winrt::TerminalApp;
using namespace TerminalApp;
static const int PaneBorderSize = 2;
static const int CombinedPaneBorderSize = 2 * PaneBorderSize;
@@ -58,6 +59,7 @@ Pane::Pane(const GUID& profile, const TermControl& control, const bool lastFocus
// Register an event with the control to have it inform us when it gains focus.
_gotFocusRevoker = control.GotFocus(winrt::auto_revoke, { this, &Pane::_ControlGotFocusHandler });
_lostFocusRevoker = control.LostFocus(winrt::auto_revoke, { this, &Pane::_ControlLostFocusHandler });
// When our border is tapped, make sure to transfer focus to our control.
// LOAD-BEARING: This will NOT work if the border's BorderBrush is set to
@@ -366,15 +368,18 @@ void Pane::_ControlWarningBellHandler(const winrt::Windows::Foundation::IInspect
auto paneProfile = settings.FindProfile(_profile.value());
if (paneProfile)
{
if (WI_IsFlagSet(paneProfile.BellStyle(), winrt::Microsoft::Terminal::Settings::Model::BellStyle::Audible))
// We don't want to do anything if nothing is set, so check for that first
if (static_cast<int>(paneProfile.BellStyle()) != 0)
{
const auto soundAlias = reinterpret_cast<LPCTSTR>(SND_ALIAS_SYSTEMHAND);
PlaySound(soundAlias, NULL, SND_ALIAS_ID | SND_ASYNC | SND_SENTRY);
}
if (WI_IsFlagSet(paneProfile.BellStyle(), winrt::Microsoft::Terminal::Settings::Model::BellStyle::Visual))
{
// Bubble this event up to app host, starting with bubbling to the hosting tab
_PaneRaiseVisualBellHandlers(nullptr);
if (WI_IsFlagSet(paneProfile.BellStyle(), winrt::Microsoft::Terminal::Settings::Model::BellStyle::Audible))
{
// Audible is set, play the sound
const auto soundAlias = reinterpret_cast<LPCTSTR>(SND_ALIAS_SYSTEMHAND);
PlaySound(soundAlias, NULL, SND_ALIAS_ID | SND_ASYNC | SND_SENTRY);
}
// raise the event with the bool value corresponding to the visual flag
_PaneRaiseBellHandlers(nullptr, WI_IsFlagSet(paneProfile.BellStyle(), winrt::Microsoft::Terminal::Settings::Model::BellStyle::Visual));
}
}
}
@@ -393,6 +398,16 @@ void Pane::_ControlGotFocusHandler(winrt::Windows::Foundation::IInspectable cons
_GotFocusHandlers(shared_from_this());
}
// Event Description:
// - Called when our control loses focus. We'll use this to trigger our LostFocus
// callback. The tab that's hosting us should have registered a callback which
// can be used to update its own internal focus state
void Pane::_ControlLostFocusHandler(winrt::Windows::Foundation::IInspectable const& /* sender */,
RoutedEventArgs const& /* args */)
{
_LostFocusHandlers(shared_from_this());
}
// Method Description:
// - Fire our Closed event to tell our parent that we should be removed.
// Arguments:
@@ -715,6 +730,7 @@ void Pane::_CloseChild(const bool closeFirst)
// re-attach our handler for the control's GotFocus event.
_gotFocusRevoker = _control.GotFocus(winrt::auto_revoke, { this, &Pane::_ControlGotFocusHandler });
_lostFocusRevoker = _control.LostFocus(winrt::auto_revoke, { this, &Pane::_ControlLostFocusHandler });
// If we're inheriting the "last active" state from one of our children,
// focus our control now. This should trigger our own GotFocus event.
@@ -1420,6 +1436,7 @@ std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Pane::_Split(SplitState
// control telling us that it's now focused, we want it telling its new
// parent.
_gotFocusRevoker.revoke();
_lostFocusRevoker.revoke();
_splitState = actualSplitType;
_desiredSplitPosition = 1.0f - splitSize;
@@ -1533,9 +1550,9 @@ void Pane::Restore(std::shared_ptr<Pane> zoomedPane)
// otherwise the ID value will not make sense (leaves have IDs, parents do not)
// Return Value:
// - The ID of this pane
uint16_t Pane::Id() noexcept
std::optional<uint16_t> Pane::Id() noexcept
{
return _id.value();
return _id;
}
// Method Description:
@@ -2069,4 +2086,5 @@ std::optional<SplitState> Pane::PreCalculateAutoSplit(const std::shared_ptr<Pane
}
DEFINE_EVENT(Pane, GotFocus, _GotFocusHandlers, winrt::delegate<std::shared_ptr<Pane>>);
DEFINE_EVENT(Pane, PaneRaiseVisualBell, _PaneRaiseVisualBellHandlers, winrt::delegate<std::shared_ptr<Pane>>);
DEFINE_EVENT(Pane, LostFocus, _LostFocusHandlers, winrt::delegate<std::shared_ptr<Pane>>);
DEFINE_EVENT(Pane, PaneRaiseBell, _PaneRaiseBellHandlers, winrt::Windows::Foundation::EventHandler<bool>);

View File

@@ -77,13 +77,14 @@ public:
void Maximize(std::shared_ptr<Pane> zoomedPane);
void Restore(std::shared_ptr<Pane> zoomedPane);
uint16_t Id() noexcept;
std::optional<uint16_t> Id() noexcept;
void Id(uint16_t id) noexcept;
void FocusPane(const uint16_t id);
WINRT_CALLBACK(Closed, winrt::Windows::Foundation::EventHandler<winrt::Windows::Foundation::IInspectable>);
DECLARE_EVENT(GotFocus, _GotFocusHandlers, winrt::delegate<std::shared_ptr<Pane>>);
DECLARE_EVENT(PaneRaiseVisualBell, _PaneRaiseVisualBellHandlers, winrt::delegate<std::shared_ptr<Pane>>);
DECLARE_EVENT(LostFocus, _LostFocusHandlers, winrt::delegate<std::shared_ptr<Pane>>);
DECLARE_EVENT(PaneRaiseBell, _PaneRaiseBellHandlers, winrt::Windows::Foundation::EventHandler<bool>);
private:
struct SnapSizeResult;
@@ -111,6 +112,7 @@ private:
winrt::event_token _warningBellToken{ 0 };
winrt::Windows::UI::Xaml::UIElement::GotFocus_revoker _gotFocusRevoker;
winrt::Windows::UI::Xaml::UIElement::LostFocus_revoker _lostFocusRevoker;
std::shared_mutex _createCloseLock{};
@@ -144,6 +146,8 @@ private:
winrt::Windows::Foundation::IInspectable const& e);
void _ControlGotFocusHandler(winrt::Windows::Foundation::IInspectable const& sender,
winrt::Windows::UI::Xaml::RoutedEventArgs const& e);
void _ControlLostFocusHandler(winrt::Windows::Foundation::IInspectable const& sender,
winrt::Windows::UI::Xaml::RoutedEventArgs const& e);
std::pair<float, float> _CalcChildrenSizes(const float fullSize) const;
SnapChildrenSizeResult _CalcSnappedChildrenSizes(const bool widthOrHeight, const float fullSize) const;

View File

@@ -1,17 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
@@ -26,36 +26,36 @@
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
@@ -226,6 +226,9 @@
<value>&#x2022; Found a keybinding with too many strings for the "keys" array. There should only be one string value in the "keys" array.</value>
<comment>{Locked="\"keys\"","&#x2022;"} This glyph is a bullet, used in a bulleted list.</comment>
</data>
<data name="FailedToParseSubCommands" xml:space="preserve">
<value>&#x2022; Failed to parse all subcommands of nested command.</value>
</data>
<data name="MissingRequiredParameter" xml:space="preserve">
<value>&#x2022; Found a keybinding that was missing a required parameter value. This keybinding will be ignored.</value>
<comment>{Locked="&#x2022;"} This glyph is a bullet, used in a bulleted list.</comment>
@@ -257,6 +260,84 @@
<value>Failed to parse "startupActions".</value>
<comment>{Locked="\"startupActions\""}</comment>
</data>
<data name="CmdCommandArgDesc" xml:space="preserve">
<value>An optional command, with arguments, to be spawned in the new tab or pane</value>
</data>
<data name="CmdFocusTabDesc" xml:space="preserve">
<value>Move focus to another tab</value>
</data>
<data name="CmdFocusTabNextArgDesc" xml:space="preserve">
<value>Move focus to the next tab</value>
</data>
<data name="CmdFTDesc" xml:space="preserve">
<value>An alias for the "focus-tab" subcommand.</value>
<comment>{Locked="\"focus-tab\""}</comment>
</data>
<data name="CmdFocusTabPrevArgDesc" xml:space="preserve">
<value>Move focus to the previous tab</value>
</data>
<data name="CmdFocusTabTargetArgDesc" xml:space="preserve">
<value>Move focus the tab at the given index</value>
</data>
<data name="CmdSplitPaneSizeArgDesc" xml:space="preserve">
<value>Specify the size as a percentage of the parent pane. Valid values are between (0,1), exclusive.</value>
</data>
<data name="CmdNewTabDesc" xml:space="preserve">
<value>Create a new tab</value>
</data>
<data name="CmdNTDesc" xml:space="preserve">
<value>An alias for the "new-tab" subcommand.</value>
<comment>{Locked="\"new-tab\""}</comment>
</data>
<data name="CmdProfileArgDesc" xml:space="preserve">
<value>Open with the given profile. Accepts either the name or GUID of a profile</value>
</data>
<data name="CmdSplitPaneDesc" xml:space="preserve">
<value>Create a new split pane</value>
</data>
<data name="CmdSPDesc" xml:space="preserve">
<value>An alias for the "split-pane" subcommand.</value>
<comment>{Locked="\"split-pane\""}</comment>
</data>
<data name="CmdSplitPaneHorizontalArgDesc" xml:space="preserve">
<value>Create the new pane as a horizontal split (think [-])</value>
</data>
<data name="CmdSplitPaneVerticalArgDesc" xml:space="preserve">
<value>Create the new pane as a vertical split (think [|])</value>
</data>
<data name="CmdStartingDirArgDesc" xml:space="preserve">
<value>Open in the given directory instead of the profile's set "startingDirectory"</value>
<comment>{Locked="\"startingDirectory\""}</comment>
</data>
<data name="CmdTitleArgDesc" xml:space="preserve">
<value>Open the terminal with the provided title instead of the profile's set "title"</value>
<comment>{Locked="\"title\""}</comment>
</data>
<data name="CmdTabColorArgDesc" xml:space="preserve">
<value>Open the tab with the specified color, in #rrggbb format</value>
</data>
<data name="CmdVersionDesc" xml:space="preserve">
<value>Display the application version</value>
</data>
<data name="CmdMaximizedDesc" xml:space="preserve">
<value>Launch the window maximized</value>
</data>
<data name="CmdFullscreenDesc" xml:space="preserve">
<value>Launch the window in fullscreen mode</value>
</data>
<data name="CmdMoveFocusDesc" xml:space="preserve">
<value>Move focus to the adjacent pane in the specified direction</value>
</data>
<data name="CmdMFDesc" xml:space="preserve">
<value>An alias for the "move-focus" subcommand.</value>
<comment>{Locked="\"move-focus\""}</comment>
</data>
<data name="CmdMoveFocusDirectionArgDesc" xml:space="preserve">
<value>The direction to move focus in</value>
</data>
<data name="CmdFocusDesc" xml:space="preserve">
<value>Launch the window in focus mode</value>
</data>
<data name="NewTabSplitButton.[using:Windows.UI.Xaml.Automation]AutomationProperties.HelpText" xml:space="preserve">
<value>Press the button to open a new terminal tab with your default profile. Open the flyout to select which profile you want to open.</value>
</data>
@@ -278,9 +359,6 @@
<data name="WindowMaximizeButton.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<value>Maximize</value>
</data>
<data name="WindowMaximizeButton.[using:Windows.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
<value>Maximize</value>
</data>
<data name="WindowMinimizeButton.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<value>Minimize</value>
</data>
@@ -358,7 +436,7 @@
</data>
<data name="CommandPalette_ParsedCommandLine" xml:space="preserve">
<value>Executing command line will invoke the following commands:</value>
<comment>Will be followed by a list of strings describing parsed commands</comment>
<comment>Will be followed by a list of strings describing parsed commands</comment>
</data>
<data name="CommandPalette_FailedParsingCommandLine" xml:space="preserve">
<value>Failed parsing command line:</value>
@@ -466,4 +544,13 @@
<data name="ClipboardTextHeader.Text" xml:space="preserve">
<value>Clipboard contents (preview):</value>
</data>
</root>
<data name="CommandPalette_MoreOptions.[using:Windows.UI.Xaml.Automation]AutomationProperties.HelpText" xml:space="preserve">
<value>More options</value>
</data>
<data name="WindowMaximizeButtonToolTip" xml:space="preserve">
<value>Maximize</value>
</data>
<data name="WindowRestoreDownButtonToolTip" xml:space="preserve">
<value>Restore Down</value>
</data>
</root>

View File

@@ -22,6 +22,11 @@ namespace winrt::TerminalApp::implementation
// - true if we handled the event was handled, else false.
bool ShortcutActionDispatch::DoAction(const ActionAndArgs& actionAndArgs)
{
if (!actionAndArgs)
{
return false;
}
const auto& action = actionAndArgs.Action();
const auto& args = actionAndArgs.Args();
auto eventArgs = args ? ActionEventArgs{ args } :

View File

@@ -49,7 +49,7 @@ namespace winrt::TerminalApp::implementation
Controls::MenuFlyoutItem closeTabMenuItem;
Controls::FontIcon closeSymbol;
closeSymbol.FontFamily(Media::FontFamily{ L"Segoe MDL2 Assets" });
closeSymbol.Glyph(L"\xE8BB");
closeSymbol.Glyph(L"\xE711");
closeTabMenuItem.Click([weakThis](auto&&, auto&&) {
if (auto tab{ weakThis.get() })
@@ -62,7 +62,6 @@ namespace winrt::TerminalApp::implementation
// Build the menu
Controls::MenuFlyout newTabFlyout;
newTabFlyout.Items().Append(_CreateCloseSubMenu());
newTabFlyout.Items().Append(closeTabMenuItem);
TabViewItem().ContextFlyout(newTabFlyout);
}
@@ -183,6 +182,17 @@ namespace winrt::TerminalApp::implementation
}
}
// Method Description:
// - Creates a text for the title run in the tool tip by returning tab title
// Arguments:
// - <none>
// Return Value:
// - The value to populate in the title run of the tool tip
winrt::hstring TabBase::_CreateToolTipTitle()
{
return _Title;
}
// Method Description:
// - Sets tab tool tip to a concatenation of title and key chord
// Arguments:
@@ -192,7 +202,7 @@ namespace winrt::TerminalApp::implementation
void TabBase::_UpdateToolTip()
{
auto titleRun = WUX::Documents::Run();
titleRun.Text(_Title);
titleRun.Text(_CreateToolTipTitle());
auto textBlock = WUX::Controls::TextBlock{};
textBlock.TextAlignment(WUX::TextAlignment::Center);

View File

@@ -48,6 +48,8 @@ namespace winrt::TerminalApp::implementation
winrt::hstring _keyChord{};
virtual void _CreateContextMenu();
virtual winrt::hstring _CreateToolTipTitle();
winrt::Windows::UI::Xaml::Controls::MenuFlyoutSubItem _CreateCloseSubMenu();
void _EnableCloseMenuItems();
void _CloseTabsAfter();

View File

@@ -65,7 +65,7 @@ namespace winrt::TerminalApp::implementation
"TabRenamerOpened",
TraceLoggingDescription("Event emitted when the tab renamer is opened"),
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
TelemetryPrivacyDataTag(PDT_ProductAndServicePerformance));
TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
}
// Method Description:
@@ -75,6 +75,14 @@ namespace winrt::TerminalApp::implementation
void TabHeaderControl::RenameBoxLostFocusHandler(Windows::Foundation::IInspectable const& /*sender*/,
Windows::UI::Xaml::RoutedEventArgs const& /*e*/)
{
// If the context menu associated with the renamer text box is open we know it gained the focus.
// In this case we ignore this event (we will regain the focus once the menu will be closed).
const auto flyout = HeaderRenamerTextBox().ContextFlyout();
if (flyout && flyout.IsOpen())
{
return;
}
// Log the data here, rather than in _CloseRenameBox. If we do it there,
// it'll get fired twice, once when the key is pressed to commit/cancel,
// and then again when the focus is lost
@@ -85,7 +93,7 @@ namespace winrt::TerminalApp::implementation
TraceLoggingDescription("Event emitted when the tab renamer is closed"),
TraceLoggingBoolean(_renameCancelled, "CancelledRename", "True if the user cancelled the rename, false if they committed."),
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
TelemetryPrivacyDataTag(PDT_ProductAndServicePerformance));
TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
_CloseRenameBox();
if (!_renameCancelled)
@@ -98,7 +106,11 @@ namespace winrt::TerminalApp::implementation
// - Hides the rename box and displays the title text block
void TabHeaderControl::_CloseRenameBox()
{
HeaderRenamerTextBox().Visibility(Windows::UI::Xaml::Visibility::Collapsed);
HeaderTextBlock().Visibility(Windows::UI::Xaml::Visibility::Visible);
if (HeaderRenamerTextBox().Visibility() == Windows::UI::Xaml::Visibility::Visible)
{
HeaderRenamerTextBox().Visibility(Windows::UI::Xaml::Visibility::Collapsed);
HeaderTextBlock().Visibility(Windows::UI::Xaml::Visibility::Visible);
_RenameEndedHandlers(*this, nullptr);
}
}
}

View File

@@ -26,8 +26,11 @@ namespace winrt::TerminalApp::implementation
OBSERVABLE_GETSET_PROPERTY(double, RenamerMaxWidth, _PropertyChangedHandlers);
OBSERVABLE_GETSET_PROPERTY(bool, IsProgressRingActive, _PropertyChangedHandlers);
OBSERVABLE_GETSET_PROPERTY(bool, IsProgressRingIndeterminate, _PropertyChangedHandlers);
OBSERVABLE_GETSET_PROPERTY(bool, BellIndicator, _PropertyChangedHandlers);
OBSERVABLE_GETSET_PROPERTY(uint32_t, ProgressValue, _PropertyChangedHandlers);
TYPED_EVENT(RenameEnded, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
private:
bool _receivedKeyDown{ false };
bool _renameCancelled{ false };

View File

@@ -12,11 +12,13 @@ namespace TerminalApp
Double RenamerMaxWidth { get; set; };
Boolean IsProgressRingActive { get; set; };
Boolean IsProgressRingIndeterminate { get; set; };
Boolean BellIndicator { get; set; };
UInt32 ProgressValue { get; set; };
TabHeaderControl();
void BeginRename();
event TitleChangeRequestedArgs TitleChangeRequested;
event Windows.Foundation.TypedEventHandler<Object, Object> RenameEnded;
}
}

View File

@@ -43,6 +43,12 @@ the MIT License. See LICENSE in the project root for license information. -->
<!--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"
FontFamily="Segoe MDL2 Assets"
Visibility="{x:Bind BellIndicator, Mode=OneWay}"
Glyph="&#xEA8F;"
FontSize="12"
Margin="0,0,8,0"/>
<FontIcon x:Name="HeaderZoomIcon"
FontFamily="Segoe MDL2 Assets"
Visibility="{x:Bind IsPaneZoomed, Mode=OneWay}"

View File

@@ -25,8 +25,7 @@
<ClCompile>
<!-- For CLI11: It uses dynamic_cast to cast types around, which depends
on being compiled with RTTI (/GR). We need this in this project, because
we're including the CLI11 header via the CommandlineArgs project. -->
on being compiled with RTTI (/GR). -->
<RuntimeTypeInfo>true</RuntimeTypeInfo>
</ClCompile>
</ItemDefinitionGroup>
@@ -72,6 +71,8 @@
<ItemGroup>
<ClInclude Include="ActionPaletteItem.h" />
<ClInclude Include="App.base.h" />
<ClInclude Include="AppCommandlineArgs.h" />
<ClInclude Include="Commandline.h" />
<ClInclude Include="CommandLinePaletteItem.h" />
<ClInclude Include="Jumplist.h" />
<ClInclude Include="MinMaxCloseControl.h">
@@ -143,6 +144,8 @@
<ClCompile Include="ActionPaletteItem.cpp" />
<ClCompile Include="CommandLinePaletteItem.cpp" />
<ClCompile Include="init.cpp" />
<ClCompile Include="AppCommandlineArgs.cpp" />
<ClCompile Include="Commandline.cpp" />
<ClCompile Include="Jumplist.cpp" />
<ClCompile Include="MinMaxCloseControl.cpp">
<DependentUpon>MinMaxCloseControl.xaml</DependentUpon>
@@ -273,13 +276,7 @@
</ItemGroup>
<!-- ========================= Misc Files ======================== -->
<ItemGroup>
<PRIResource Include="Resources\en-US\Resources.resw">
<SubType>Designer</SubType>
</PRIResource>
<!-- Make sure to include the CommandlineArgs resources here, so they show up in our scope -->
<PRIResource Include="$(OpenConsoleDir)src\cascadia\CommandlineArgs\Resources\en-US\Resources.resw">
<SubType>Designer</SubType>
</PRIResource>
<PRIResource Include="Resources\en-US\Resources.resw" />
<OCResourceDirectory Include="Resources" />
<None Include="packages.config" />
</ItemGroup>
@@ -291,14 +288,6 @@
you also update all the consumers
-->
<ProjectReference Include="$(OpenConsoleDir)src\types\lib\types.vcxproj" />
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\CommandlineArgs\CommandlineArgs.vcxproj" >
<Private>true</Private>
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
<!-- Make sure to set ReferenceOutputAssembly=false, or we'll try and
MDMERGE with MUX from the CommandlineArgs output, and get duplicate type
errors everywhere. -->
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\WinRTUtils\WinRTUtils.vcxproj">
<Project>{CA5CAD1A-039A-4929-BA2A-8BEB2E4106FE}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>

View File

@@ -135,6 +135,8 @@ namespace winrt::TerminalApp::implementation
}
CATCH_LOG();
_tabRow.PointerMoved({ this, &TerminalPage::_RestorePointerCursorHandler });
_tabView.CanReorderTabs(!isElevated);
_tabView.CanDragTabs(!isElevated);
@@ -253,6 +255,13 @@ namespace winrt::TerminalApp::implementation
_layoutUpdatedRevoker = _tabContent.LayoutUpdated(winrt::auto_revoke, { this, &TerminalPage::_OnFirstLayout });
_isAlwaysOnTop = _settings.GlobalSettings().AlwaysOnTop();
// Setup mouse vanish attributes
SystemParametersInfoW(SPI_GETMOUSEVANISH, 0, &_shouldMouseVanish, false);
// Store cursor, so we can restore it, e.g., after mouse vanishing
// (we'll need to adapt this logic once we make cursor context aware)
_defaultPointerCursor = CoreWindow::GetForCurrentThread().PointerCursor();
}
// Method Description:
@@ -808,6 +817,19 @@ namespace winrt::TerminalApp::implementation
}
});
newTabImpl->TabRenamerDeactivated([weakThis{ get_weak() }](auto&& /*s*/, auto&& /*e*/) {
if (const auto page{ weakThis.get() })
{
if (!page->_newTabButton.Flyout().IsOpen())
{
if (const auto tab{ page->_GetFocusedTab() })
{
tab.Focus(FocusState::Programmatic);
}
}
}
});
if (debugConnection) // this will only be set if global debugging is on and tap is active
{
TermControl newControl{ settings, debugConnection };
@@ -957,6 +979,30 @@ namespace winrt::TerminalApp::implementation
}
}
// Method Description:
// Handles preview key on the SUI tab, by handling close tab / next tab / previous tab
// This is a temporary solution - we need to fix all key-bindings work from SUI as long as they don't harm
// the SUI behavior
// Arguments:
// - e: the KeyRoutedEventArgs containing info about the keystroke.
// Return Value:
// - <none>
void TerminalPage::_SUIPreviewKeyDownHandler(Windows::Foundation::IInspectable const& /*sender*/, Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e)
{
auto key = e.OriginalKey();
auto const ctrlDown = WI_IsFlagSet(CoreWindow::GetForCurrentThread().GetKeyState(winrt::Windows::System::VirtualKey::Control), CoreVirtualKeyStates::Down);
auto const altDown = WI_IsFlagSet(CoreWindow::GetForCurrentThread().GetKeyState(winrt::Windows::System::VirtualKey::Menu), CoreVirtualKeyStates::Down);
auto const shiftDown = WI_IsFlagSet(CoreWindow::GetForCurrentThread().GetKeyState(winrt::Windows::System::VirtualKey::Shift), CoreVirtualKeyStates::Down);
winrt::Microsoft::Terminal::TerminalControl::KeyChord kc{ ctrlDown, altDown, shiftDown, static_cast<int32_t>(key) };
const auto actionAndArgs = _settings.KeyMap().TryLookup(kc);
if (actionAndArgs && (actionAndArgs.Action() == ShortcutAction::CloseTab || actionAndArgs.Action() == ShortcutAction::NextTab || actionAndArgs.Action() == ShortcutAction::PrevTab || actionAndArgs.Action() == ShortcutAction::ClosePane))
{
_actionDispatch->DoAction(actionAndArgs);
e.Handled(true);
}
}
// Method Description:
// - Configure the AppKeyBindings to use our ShortcutActionDispatch and the updated KeyMapping
// as the object to handle dispatching ShortcutAction events.
@@ -1034,8 +1080,7 @@ namespace winrt::TerminalApp::implementation
{
auto newTabTitle = tab.Title();
if (_settings.GlobalSettings().ShowTitleInTitlebar() &&
tab.FocusState() != FocusState::Unfocused)
if (_settings.GlobalSettings().ShowTitleInTitlebar() && tab == _GetFocusedTab())
{
_titleChangeHandlers(*this, newTabTitle);
}
@@ -1260,6 +1305,9 @@ namespace winrt::TerminalApp::implementation
// Add an event handler for when the terminal wants to set a progress indicator on the taskbar
term.SetTaskbarProgress({ this, &TerminalPage::_SetTaskbarProgressHandler });
term.HidePointerCursor({ this, &TerminalPage::_HidePointerCursorHandler });
term.RestorePointerCursor({ this, &TerminalPage::_RestorePointerCursorHandler });
// Bind Tab events to the TermControl and the Tab's Pane
hostingTab.Initialize(term);
@@ -1520,6 +1568,13 @@ namespace winrt::TerminalApp::implementation
_UnZoomIfNeeded();
terminalTab->ClosePane();
}
else if (auto index{ _GetFocusedTabIndex() })
{
if (_tabs.GetAt(*index).try_as<TerminalApp::SettingsTab>())
{
_RemoveTabViewItemByIndex(*index);
}
}
}
// Method Description:
@@ -2208,8 +2263,13 @@ namespace winrt::TerminalApp::implementation
_UpdateMRUTab(index);
}
tab.TabViewItem().StartBringIntoView();
// Raise an event that our title changed
_titleChangeHandlers(*this, tab.Title());
if (_settings.GlobalSettings().ShowTitleInTitlebar())
{
_titleChangeHandlers(*this, tab.Title());
}
}
CATCH_LOG();
}
@@ -2367,7 +2427,7 @@ namespace winrt::TerminalApp::implementation
IVectorView<Profile> profiles,
IMapView<winrt::hstring, ColorScheme> schemes)
{
IVector<SettingsLoadWarnings> warnings;
IVector<SettingsLoadWarnings> warnings{ winrt::single_threaded_vector<SettingsLoadWarnings>() };
std::vector<ColorScheme> sortedSchemes;
sortedSchemes.reserve(schemes.Size());
@@ -2712,7 +2772,7 @@ namespace winrt::TerminalApp::implementation
// - an empty list if we failed to parse, otherwise a list of actions to execute.
std::vector<ActionAndArgs> TerminalPage::ConvertExecuteCommandlineToActions(const ExecuteCommandlineArgs& args)
{
::Microsoft::Terminal::CommandlineArgs::AppCommandlineArgs appArgs;
::TerminalApp::AppCommandlineArgs appArgs;
if (appArgs.ParseArgs(args) == 0)
{
return appArgs.GetStartupActions();
@@ -2795,6 +2855,8 @@ namespace winrt::TerminalApp::implementation
sui.SetHostingWindow(reinterpret_cast<uint64_t>(*_hostingHwnd));
}
sui.PreviewKeyDown({ this, &TerminalPage::_SUIPreviewKeyDownHandler });
sui.OpenJson([weakThis{ get_weak() }](auto&& /*s*/, winrt::Microsoft::Terminal::Settings::Model::SettingsTarget e) {
if (auto page{ weakThis.get() })
{
@@ -3012,6 +3074,32 @@ namespace winrt::TerminalApp::implementation
return text;
}
// Method Description:
// - Hides cursor if required
// Return Value:
// - <none>
void TerminalPage::_HidePointerCursorHandler(const IInspectable& /*sender*/, const IInspectable& /*eventArgs*/)
{
if (_shouldMouseVanish && !_isMouseHidden)
{
CoreWindow::GetForCurrentThread().PointerCursor(nullptr);
_isMouseHidden = true;
}
}
// Method Description:
// - Restores cursor if required
// Return Value:
// - <none>
void TerminalPage::_RestorePointerCursorHandler(const IInspectable& /*sender*/, const IInspectable& /*eventArgs*/)
{
if (_isMouseHidden)
{
CoreWindow::GetForCurrentThread().PointerCursor(_defaultPointerCursor);
_isMouseHidden = false;
}
}
// -------------------------------- WinRT Events ---------------------------------
// Winrt events need a method for adding a callback to the event and removing the callback.
// These macros will define them both for you.

View File

@@ -10,7 +10,7 @@
#include <winrt/Microsoft.Terminal.TerminalControl.h>
#include "../CommandlineArgs/AppCommandlineArgs.h"
#include "AppCommandlineArgs.h"
static constexpr uint32_t DefaultRowsToScroll{ 3 };
static constexpr std::wstring_view TabletInputServiceKey{ L"TabletInputService" };
@@ -159,6 +159,7 @@ namespace winrt::TerminalApp::implementation
void _ThirdPartyNoticesOnClick(const IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& eventArgs);
void _KeyDownHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e);
void _SUIPreviewKeyDownHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e);
void _HookupKeyBindings(const Microsoft::Terminal::Settings::Model::KeyMapping& keymap) noexcept;
void _RegisterActionCallbacks();
@@ -261,6 +262,12 @@ namespace winrt::TerminalApp::implementation
void _TryMoveTab(const uint32_t currentTabIndex, const int32_t suggestedNewTabIndex);
bool _shouldMouseVanish{ false };
bool _isMouseHidden{ false };
Windows::UI::Core::CoreCursor _defaultPointerCursor{ nullptr };
void _HidePointerCursorHandler(const IInspectable& sender, const IInspectable& eventArgs);
void _RestorePointerCursorHandler(const IInspectable& sender, const IInspectable& eventArgs);
#pragma region ActionHandlers
// These are all defined in AppActionHandlers.cpp
void _HandleOpenNewTabDropdown(const IInspectable& sender, const Microsoft::Terminal::Settings::Model::ActionEventArgs& args);

View File

@@ -57,6 +57,22 @@ namespace winrt::TerminalApp::implementation
TabViewItem().Header(_headerControl);
}
// Method Description:
// - Called when the timer for the bell indicator in the tab header fires
// - Removes the bell indicator from the tab header
// Arguments:
// - sender, e: not used
void TerminalTab::_BellIndicatorTimerTick(Windows::Foundation::IInspectable const& /*sender*/, Windows::Foundation::IInspectable const& /*e*/)
{
ShowBellIndicator(false);
// Just do a sanity check that the timer still exists before we stop it
if (_bellIndicatorTimer.has_value())
{
_bellIndicatorTimer->Stop();
_bellIndicatorTimer = std::nullopt;
}
}
// Method Description:
// - Initializes a TabViewItem for this Tab instance.
// Arguments:
@@ -145,6 +161,11 @@ namespace winrt::TerminalApp::implementation
lastFocusedControl.Focus(_focusState);
lastFocusedControl.TaskbarProgressChanged();
}
// When we gain focus, remove the bell indicator if it is active
if (_headerControl.BellIndicator())
{
ShowBellIndicator(false);
}
}
}
@@ -255,6 +276,44 @@ namespace winrt::TerminalApp::implementation
}
}
// Method Description:
// - Hide or show the bell indicator in the tab header
// Arguments:
// - show: if true, we show the indicator; if false, we hide the indicator
winrt::fire_and_forget TerminalTab::ShowBellIndicator(const bool show)
{
auto weakThis{ get_weak() };
co_await winrt::resume_foreground(TabViewItem().Dispatcher());
if (auto tab{ weakThis.get() })
{
tab->_headerControl.BellIndicator(show);
}
}
// Method Description:
// - Activates the timer for the bell indicator in the tab
// - Called if a bell raised when the tab already has focus
winrt::fire_and_forget TerminalTab::ActivateBellIndicatorTimer()
{
auto weakThis{ get_weak() };
co_await winrt::resume_foreground(TabViewItem().Dispatcher());
if (auto tab{ weakThis.get() })
{
if (!tab->_bellIndicatorTimer.has_value())
{
DispatcherTimer bellIndicatorTimer;
bellIndicatorTimer.Interval(std::chrono::milliseconds(2000));
bellIndicatorTimer.Tick({ get_weak(), &TerminalTab::_BellIndicatorTimerTick });
bellIndicatorTimer.Start();
tab->_bellIndicatorTimer.emplace(std::move(bellIndicatorTimer));
}
}
}
// Method Description:
// - Gets the title string of the last focused terminal control in our tree.
// Returns the empty string if there is no such control.
@@ -292,6 +351,7 @@ namespace winrt::TerminalApp::implementation
// Update the control to reflect the changed title
_headerControl.Title(activeTitle);
Automation::AutomationProperties::SetName(tab->TabViewItem(), activeTitle);
_UpdateToolTip();
}
}
@@ -311,7 +371,7 @@ namespace winrt::TerminalApp::implementation
co_await winrt::resume_foreground(control.Dispatcher());
const auto currentOffset = control.GetScrollOffset();
control.ScrollViewport(currentOffset + delta);
control.ScrollViewport(::base::ClampAdd(currentOffset, delta));
}
// Method Description:
@@ -331,9 +391,19 @@ namespace winrt::TerminalApp::implementation
// Make sure to take the ID before calling Split() - Split() will clear out the active pane's ID
const auto activePaneId = _activePane->Id();
auto [first, second] = _activePane->Split(splitType, splitSize, profile, control);
first->Id(activePaneId);
second->Id(_nextPaneId);
++_nextPaneId;
if (activePaneId)
{
first->Id(activePaneId.value());
second->Id(_nextPaneId);
++_nextPaneId;
}
else
{
first->Id(_nextPaneId);
++_nextPaneId;
second->Id(_nextPaneId);
++_nextPaneId;
}
_activePane = first;
_AttachEventHandlersToControl(control);
@@ -551,16 +621,18 @@ namespace winrt::TerminalApp::implementation
// We need to move the pane to the top of our mru list
// If its already somewhere in the list, remove it first
const auto paneId = pane->Id();
for (auto i = _mruPanes.begin(); i != _mruPanes.end(); ++i)
if (const auto paneId = pane->Id())
{
if (*i == paneId)
for (auto i = _mruPanes.begin(); i != _mruPanes.end(); ++i)
{
_mruPanes.erase(i);
break;
if (*i == paneId.value())
{
_mruPanes.erase(i);
break;
}
}
_mruPanes.insert(_mruPanes.begin(), paneId.value());
}
_mruPanes.insert(_mruPanes.begin(), paneId);
// Raise our own ActivePaneChanged event.
_ActivePaneChangedHandlers();
}
@@ -583,10 +655,30 @@ namespace winrt::TerminalApp::implementation
// Do nothing if the Tab's lifetime is expired or pane isn't new.
auto tab{ weakThis.get() };
if (tab && sender != tab->_activePane)
if (tab)
{
tab->_UpdateActivePane(sender);
tab->_RecalculateAndApplyTabColor();
if (sender != tab->_activePane)
{
tab->_UpdateActivePane(sender);
tab->_RecalculateAndApplyTabColor();
}
tab->_focusState = WUX::FocusState::Programmatic;
// This tab has gained focus, remove the bell indicator if it is active
if (tab->_headerControl.BellIndicator())
{
tab->ShowBellIndicator(false);
}
}
});
pane->LostFocus([weakThis](std::shared_ptr<Pane> /*sender*/) {
// Do nothing if the Tab's lifetime is expired or pane isn't new.
auto tab{ weakThis.get() };
if (tab)
{
// update this tab's focus state
tab->_focusState = WUX::FocusState::Unfocused;
}
});
@@ -617,13 +709,27 @@ namespace winrt::TerminalApp::implementation
}
});
// Add a PaneRaiseVisualBell event handler to the Pane. When the pane emits this event,
// we need to bubble it all the way to app host. In this part of the chain we bubble it
// from the hosting tab to the page.
pane->PaneRaiseVisualBell([weakThis](auto&& /*s*/) {
// Add a PaneRaiseBell event handler to the Pane
pane->PaneRaiseBell([weakThis](auto&& /*s*/, auto&& visual) {
if (auto tab{ weakThis.get() })
{
tab->_TabRaiseVisualBellHandlers();
if (visual)
{
// If visual is set, we need to bubble this event all the way to app host to flash the taskbar
// In this part of the chain we bubble it from the hosting tab to the page
tab->_TabRaiseVisualBellHandlers();
}
// Show the bell indicator in the tab header
tab->ShowBellIndicator(true);
// If this tab is focused, activate the bell indicator timer, which will
// remove the bell indicator once it fires
// (otherwise, the indicator is removed when the tab gets focus)
if (tab->_focusState != WUX::FocusState::Unfocused)
{
tab->ActivateBellIndicatorTimer();
}
}
});
}
@@ -708,7 +814,6 @@ namespace winrt::TerminalApp::implementation
newTabFlyout.Items().Append(chooseColorMenuItem);
newTabFlyout.Items().Append(renameTabMenuItem);
newTabFlyout.Items().Append(menuSeparator);
newTabFlyout.Items().Append(_CreateCloseSubMenu());
newTabFlyout.Items().Append(closeTabMenuItem);
TabViewItem().ContextFlyout(newTabFlyout);
}
@@ -1006,6 +1111,27 @@ namespace winrt::TerminalApp::implementation
return _zoomedPane != nullptr;
}
// Method Description:
// - Creates a text for the title run in the tool tip by returning tab title
// or <profile name>: <tab title> in the case the profile name differs from the title
// Arguments:
// - <none>
// Return Value:
// - The value to populate in the title run of the tool tip
winrt::hstring TerminalTab::_CreateToolTipTitle()
{
if (const auto& control{ GetActiveTerminalControl() })
{
const auto profileName{ control.Settings().ProfileName() };
if (profileName != Title())
{
return fmt::format(L"{}: {}", profileName, Title()).data();
}
}
return Title();
}
DEFINE_EVENT(TerminalTab, ActivePaneChanged, _ActivePaneChangedHandlers, winrt::delegate<>);
DEFINE_EVENT(TerminalTab, ColorSelected, _colorSelected, winrt::delegate<winrt::Windows::UI::Color>);
DEFINE_EVENT(TerminalTab, ColorCleared, _colorCleared, winrt::delegate<>);

View File

@@ -41,6 +41,9 @@ namespace winrt::TerminalApp::implementation
winrt::fire_and_forget UpdateIcon(const winrt::hstring iconPath);
winrt::fire_and_forget HideIcon(const bool hide);
winrt::fire_and_forget ShowBellIndicator(const bool show);
winrt::fire_and_forget ActivateBellIndicatorTimer();
float CalcSnappedDimension(const bool widthOrHeight, const float dimension) const;
winrt::Microsoft::Terminal::Settings::Model::SplitState PreCalculateAutoSplit(winrt::Windows::Foundation::Size rootSize) const;
bool PreCalculateCanSplit(winrt::Microsoft::Terminal::Settings::Model::SplitState splitType,
@@ -78,6 +81,7 @@ namespace winrt::TerminalApp::implementation
DECLARE_EVENT(ColorSelected, _colorSelected, winrt::delegate<winrt::Windows::UI::Color>);
DECLARE_EVENT(ColorCleared, _colorCleared, winrt::delegate<>);
DECLARE_EVENT(TabRaiseVisualBell, _TabRaiseVisualBellHandlers, winrt::delegate<>);
FORWARDED_TYPED_EVENT(TabRenamerDeactivated, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable, (&_headerControl), RenameEnded);
private:
std::shared_ptr<Pane> _rootPane{ nullptr };
@@ -103,11 +107,15 @@ namespace winrt::TerminalApp::implementation
winrt::TerminalApp::ShortcutActionDispatch _dispatch;
std::optional<Windows::UI::Xaml::DispatcherTimer> _bellIndicatorTimer;
void _BellIndicatorTimerTick(Windows::Foundation::IInspectable const& sender, Windows::Foundation::IInspectable const& e);
void _MakeTabViewItem();
winrt::fire_and_forget _UpdateHeaderControlMaxWidth();
void _CreateContextMenu() override;
virtual winrt::hstring _CreateToolTipTitle() override;
void _RefreshVisualState();

View File

@@ -2,5 +2,5 @@
<packages>
<package id="Microsoft.Toolkit.Win32.UI.XamlApplication" version="6.1.2" targetFramework="native" />
<package id="Microsoft.UI.Xaml" version="2.5.0-prerelease.201202003" targetFramework="native" />
<package id="Microsoft.Windows.CppWinRT" version="2.0.201017.1" targetFramework="native" />
<package id="Microsoft.Windows.CppWinRT" version="2.0.210309.3" targetFramework="native" />
</packages>

View File

@@ -76,5 +76,7 @@ TRACELOGGING_DECLARE_PROVIDER(g_hTerminalAppProvider);
#include <winrt/Windows.UI.Popups.h>
#include <CLI11/CLI11.hpp>
// Manually include til after we include Windows.Foundation to give it winrt superpowers
#include "til.h"

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Windows.CppWinRT" version="2.0.201017.1" targetFramework="native" />
<package id="Microsoft.Windows.CppWinRT" version="2.0.210309.3" targetFramework="native" />
</packages>

View File

@@ -6,7 +6,6 @@
#include "ConptyConnection.h"
#include <windows.h>
#include <userenv.h>
#include "ConptyConnection.g.cpp"
@@ -94,11 +93,8 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
environment.clear();
});
{
const auto newEnvironmentBlock{ Utils::CreateEnvironmentBlock() };
// Populate the environment map with the current environment.
RETURN_IF_FAILED(Utils::UpdateEnvironmentMapW(environment, newEnvironmentBlock.get()));
}
// Populate the environment map with the current environment.
RETURN_IF_FAILED(Utils::UpdateEnvironmentMapW(environment));
{
// Convert connection Guid to string and ignore the enclosing '{}'.

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Windows.CppWinRT" version="2.0.201017.1" targetFramework="native" />
<package id="Microsoft.Windows.CppWinRT" version="2.0.210309.3" targetFramework="native" />
<package id="vcpkg-cpprestsdk" version="2.10.14" targetFramework="native" />
</packages>

View File

@@ -78,6 +78,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
_blinkTimer{},
_lastMouseClickTimestamp{},
_lastMouseClickPos{},
_lastMouseClickPosNoSelection{},
_selectionNeedsToBeCopied{ false },
_searchBox{ nullptr }
{
@@ -86,6 +87,9 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
_terminal = std::make_unique<::Microsoft::Terminal::Core::Terminal>();
// GH#8969: pre-seed working directory to prevent potential races
_terminal->SetWorkingDirectory(_settings.StartingDirectory());
auto pfnWarningBell = std::bind(&TermControl::_TerminalWarningBell, this);
_terminal->SetWarningBellCallback(pfnWarningBell);
@@ -188,7 +192,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
_autoScrollTimer.Interval(AutoScrollUpdateInterval);
_autoScrollTimer.Tick({ this, &TermControl::_UpdateAutoScroll });
_ApplyUISettings();
_ApplyUISettings(_settings);
}
// Method Description:
@@ -274,6 +278,73 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
this->Focus(FocusState::Programmatic);
}
// Method Description:
// - Given new settings for this profile, applies the settings to the current terminal.
// - This method is separate from UpdateSettings because there is an apparent optimizer
// issue that causes one of our hstring -> wstring_view conversions to result in garbage,
// but only from a coroutine context. See GH#8723.
// - INVARIANT: This method must be called from the UI thread.
// Arguments:
// - newSettings: New settings values for the profile in this terminal.
// Return Value:
// - <none>
void TermControl::_UpdateSettingsOnUIThread(const IControlSettings& newSettings)
{
if (_closing)
{
return;
}
auto lock = _terminal->LockForWriting();
// First, store the new settings in the instance.
_settings = newSettings;
// Update our control settings
_ApplyUISettings(_settings);
// Update the terminal core with its new Core settings
_terminal->UpdateSettings(_settings);
if (!_initializedTerminal)
{
// If we haven't initialized, there's no point in continuing.
// Initialization will handle the renderer settings.
return;
}
// Update DxEngine settings under the lock
_renderEngine->SetSelectionBackground(_settings.SelectionBackground());
_renderEngine->SetRetroTerminalEffect(_settings.RetroTerminalEffect());
_renderEngine->SetPixelShaderPath(_settings.PixelShaderPath());
_renderEngine->SetForceFullRepaintRendering(_settings.ForceFullRepaintRendering());
_renderEngine->SetSoftwareRendering(_settings.SoftwareRendering());
switch (_settings.AntialiasingMode())
{
case TextAntialiasingMode::Cleartype:
_renderEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE);
break;
case TextAntialiasingMode::Aliased:
_renderEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_ALIASED);
break;
case TextAntialiasingMode::Grayscale:
default:
_renderEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE);
break;
}
// Refresh our font with the renderer
const auto actualFontOldSize = _actualFont.GetSize();
_UpdateFont();
const auto actualFontNewSize = _actualFont.GetSize();
if (actualFontNewSize != actualFontOldSize)
{
_RefreshSizeUnderLock();
}
}
// Method Description:
// - Given new settings for this profile, applies the settings to the current terminal.
// Arguments:
@@ -282,7 +353,6 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
// - <none>
winrt::fire_and_forget TermControl::UpdateSettings(IControlSettings newSettings)
{
_settings = newSettings;
auto weakThis{ get_weak() };
// Dispatch a call to the UI thread to apply the new settings to the
@@ -292,49 +362,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
// If 'weakThis' is locked, then we can safely work with 'this'
if (auto control{ weakThis.get() })
{
if (_closing)
{
co_return;
}
// Update our control settings
_ApplyUISettings();
// Update the terminal core with its new Core settings
_terminal->UpdateSettings(_settings);
auto lock = _terminal->LockForWriting();
// Update DxEngine settings under the lock
_renderEngine->SetSelectionBackground(_settings.SelectionBackground());
_renderEngine->SetRetroTerminalEffect(_settings.RetroTerminalEffect());
_renderEngine->SetPixelShaderPath(_settings.PixelShaderPath());
_renderEngine->SetForceFullRepaintRendering(_settings.ForceFullRepaintRendering());
_renderEngine->SetSoftwareRendering(_settings.SoftwareRendering());
switch (_settings.AntialiasingMode())
{
case TextAntialiasingMode::Cleartype:
_renderEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE);
break;
case TextAntialiasingMode::Aliased:
_renderEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_ALIASED);
break;
case TextAntialiasingMode::Grayscale:
default:
_renderEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE);
break;
}
// Refresh our font with the renderer
const auto actualFontOldSize = _actualFont.GetSize();
_UpdateFont();
const auto actualFontNewSize = _actualFont.GetSize();
if (actualFontNewSize != actualFontOldSize)
{
_RefreshSizeUnderLock();
}
_UpdateSettingsOnUIThread(newSettings);
}
}
@@ -384,21 +412,21 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
// - <none>
// Return Value:
// - <none>
void TermControl::_ApplyUISettings()
void TermControl::_ApplyUISettings(const IControlSettings& newSettings)
{
_InitializeBackgroundBrush();
COLORREF bg = _settings.DefaultBackground();
COLORREF bg = newSettings.DefaultBackground();
_BackgroundColorChanged(bg);
// Apply padding as swapChainPanel's margin
auto newMargin = _ParseThicknessFromPadding(_settings.Padding());
auto newMargin = _ParseThicknessFromPadding(newSettings.Padding());
SwapChainPanel().Margin(newMargin);
// Initialize our font information.
const auto fontFace = _settings.FontFace();
const short fontHeight = gsl::narrow_cast<short>(_settings.FontSize());
const auto fontWeight = _settings.FontWeight();
const auto fontFace = newSettings.FontFace();
const short fontHeight = gsl::narrow_cast<short>(newSettings.FontSize());
const auto fontWeight = newSettings.FontWeight();
// The font width doesn't terribly matter, we'll only be using the
// height to look it up
// The other params here also largely don't matter.
@@ -410,12 +438,12 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
// set TSF Foreground
Media::SolidColorBrush foregroundBrush{};
foregroundBrush.Color(static_cast<til::color>(_settings.DefaultForeground()));
foregroundBrush.Color(static_cast<til::color>(newSettings.DefaultForeground()));
TSFInputControl().Foreground(foregroundBrush);
TSFInputControl().Margin(newMargin);
// Apply settings for scrollbar
if (_settings.ScrollState() == ScrollbarState::Hidden)
if (newSettings.ScrollState() == ScrollbarState::Hidden)
{
// In the scenario where the user has turned off the OS setting to automatically hide scrollbars, the
// Terminal scrollbar would still be visible; so, we need to set the control's visibility accordingly to
@@ -869,6 +897,8 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
return;
}
_HidePointerCursorHandlers(*this, nullptr);
const auto ch = e.Character();
const auto scanCode = gsl::narrow_cast<WORD>(e.KeyStatus().ScanCode);
auto modifiers = _GetPressedModifierKeys();
@@ -1087,8 +1117,18 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
// selection.
if (_terminal->IsSelectionActive() && !KeyEvent::IsModifierKey(vkey) && vkey != VK_SNAPSHOT)
{
_terminal->ClearSelection();
_renderer->TriggerSelection();
const CoreWindow window = CoreWindow::GetForCurrentThread();
const auto leftWinKeyState = window.GetKeyState(VirtualKey::LeftWindows);
const auto rightWinKeyState = window.GetKeyState(VirtualKey::RightWindows);
const auto isLeftWinKeyDown = WI_IsFlagSet(leftWinKeyState, CoreVirtualKeyStates::Down);
const auto isRightWinKeyDown = WI_IsFlagSet(rightWinKeyState, CoreVirtualKeyStates::Down);
// GH#8791 - don't dismiss selection if Windows key was also pressed as a key-combination.
if (!isLeftWinKeyDown && !isRightWinKeyDown)
{
_terminal->ClearSelection();
_renderer->TriggerSelection();
}
if (vkey == VK_ESCAPE)
{
@@ -1213,6 +1253,8 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
return;
}
_RestorePointerCursorHandlers(*this, nullptr);
_CapturePointer(sender, args);
const auto ptr = args.Pointer();
@@ -1238,24 +1280,31 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
const auto shiftEnabled = WI_IsFlagSet(modifiers, static_cast<uint32_t>(VirtualKeyModifiers::Shift));
const auto ctrlEnabled = WI_IsFlagSet(modifiers, static_cast<uint32_t>(VirtualKeyModifiers::Control));
if (_CanSendVTMouseInput())
auto lock = _terminal->LockForWriting();
const auto cursorPosition = point.Position();
const auto terminalPosition = _GetTerminalPosition(cursorPosition);
// GH#9396: we prioritize hyper-link over VT mouse events
if (point.Properties().IsLeftButtonPressed() && ctrlEnabled && !_terminal->GetHyperlinkAtPosition(terminalPosition).empty())
{
// Handle hyper-link only on the first click to prevent multiple activations
const auto clickCount = _NumberOfClicks(cursorPosition, point.Timestamp());
if (clickCount == 1)
{
_HyperlinkHandler(_terminal->GetHyperlinkAtPosition(terminalPosition));
}
}
else if (_CanSendVTMouseInput())
{
_TrySendMouseEvent(point);
args.Handled(true);
return;
}
if (point.Properties().IsLeftButtonPressed())
else if (point.Properties().IsLeftButtonPressed())
{
auto lock = _terminal->LockForWriting();
const auto cursorPosition = point.Position();
const auto terminalPosition = _GetTerminalPosition(cursorPosition);
// Update the selection appropriately
// handle ALT key
_terminal->SetBlockSelection(altEnabled);
auto clickCount = _NumberOfClicks(cursorPosition, point.Timestamp());
const auto clickCount = _NumberOfClicks(cursorPosition, point.Timestamp());
// This formula enables the number of clicks to cycle properly between single-, double-, and triple-click.
// To increase the number of acceptable click states, simply increment MAX_CLICK_COUNT and add another if-statement
@@ -1276,41 +1325,48 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
mode = ::Terminal::SelectionExpansionMode::Line;
}
// Update the selection appropriately
if (ctrlEnabled && multiClickMapper == 1 &&
!(_terminal->GetHyperlinkAtPosition(terminalPosition).empty()))
// Capture the position of the first click when no selection is active
if (mode == ::Terminal::SelectionExpansionMode::Cell && !_terminal->IsSelectionActive())
{
_HyperlinkHandler(_terminal->GetHyperlinkAtPosition(terminalPosition));
_singleClickTouchdownPos = cursorPosition;
_lastMouseClickPosNoSelection = cursorPosition;
}
else if (shiftEnabled && _terminal->IsSelectionActive())
// We reset the active selection if one of the conditions apply:
// - shift is not held
// - GH#9384: the position is the same as of the first click starting the selection
// (we need to reset selection on double-click or triple-click, so it captures the word or the line,
// rather than extending the selection)
if (_terminal->IsSelectionActive() && (!shiftEnabled || _lastMouseClickPosNoSelection == cursorPosition))
{
// Shift+Click: only set expand on the "end" selection point
// Reset the selection
_terminal->ClearSelection();
_selectionNeedsToBeCopied = false; // there's no selection, so there's nothing to update
}
if (shiftEnabled && _terminal->IsSelectionActive())
{
// If shift is pressed and there is a selection we extend it using the selection mode
// (expand the "end"selection point)
_terminal->SetSelectionEnd(terminalPosition, mode);
_selectionNeedsToBeCopied = true;
}
else if (mode == ::Terminal::SelectionExpansionMode::Cell && !shiftEnabled)
else if (mode != ::Terminal::SelectionExpansionMode::Cell || shiftEnabled)
{
// Single Click: reset the selection and begin a new one
_terminal->ClearSelection();
_singleClickTouchdownPos = cursorPosition;
_selectionNeedsToBeCopied = false; // there's no selection, so there's nothing to update
}
else
{
// Multi-Click Selection: expand both "start" and "end" selection points
// If we are handling a double / triple-click or shift+single click
// we establish selection using the selected mode
// (expand both "start" and "end" selection points)
_terminal->MultiClickSelection(terminalPosition, mode);
_selectionNeedsToBeCopied = true;
}
_lastMouseClickTimestamp = point.Timestamp();
_lastMouseClickPos = cursorPosition;
_renderer->TriggerSelection();
}
else if (point.Properties().IsRightButtonPressed())
{
// CopyOnSelect right click always pastes
if (_settings.CopyOnSelect() || !_terminal->IsSelectionActive())
{
// CopyOnSelect right click always pastes
PasteTextFromClipboard();
}
else
@@ -1342,27 +1398,20 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
return;
}
_RestorePointerCursorHandlers(*this, nullptr);
const auto ptr = args.Pointer();
const auto point = args.GetCurrentPoint(*this);
const auto cursorPosition = point.Position();
const auto terminalPosition = _GetTerminalPosition(cursorPosition);
if (!_focused && (_terminal->GetHyperlinkAtPosition(terminalPosition).empty()))
{
args.Handled(true);
return;
}
if (ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Mouse || ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Pen)
{
if (_CanSendVTMouseInput())
if (_focused && _CanSendVTMouseInput())
{
_TrySendMouseEvent(point);
args.Handled(true);
return;
}
if (point.Properties().IsLeftButtonPressed())
else if (_focused && point.Properties().IsLeftButtonPressed())
{
auto lock = _terminal->LockForWriting();
@@ -1408,50 +1457,9 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
}
}
if (terminalPosition != _lastHoveredCell)
{
const auto uri = _terminal->GetHyperlinkAtPosition(terminalPosition);
if (!uri.empty())
{
// Update the tooltip with the URI
HoveredUri().Text(uri);
// Set the border thickness so it covers the entire cell
const auto charSizeInPixels = CharacterDimensions();
const auto htInDips = charSizeInPixels.Height / SwapChainPanel().CompositionScaleY();
const auto wtInDips = charSizeInPixels.Width / SwapChainPanel().CompositionScaleX();
const Thickness newThickness{ wtInDips, htInDips, 0, 0 };
HyperlinkTooltipBorder().BorderThickness(newThickness);
// Compute the location of the top left corner of the cell in DIPS
const til::size marginsInDips{ til::math::rounding, GetPadding().Left, GetPadding().Top };
const til::point startPos{ terminalPosition.X, terminalPosition.Y };
const til::size fontSize{ _actualFont.GetSize() };
const til::point posInPixels{ startPos * fontSize };
const til::point posInDIPs{ posInPixels / SwapChainPanel().CompositionScaleX() };
const til::point locationInDIPs{ posInDIPs + marginsInDips };
// Move the border to the top left corner of the cell
OverlayCanvas().SetLeft(HyperlinkTooltipBorder(), (locationInDIPs.x() - SwapChainPanel().ActualOffset().x));
OverlayCanvas().SetTop(HyperlinkTooltipBorder(), (locationInDIPs.y() - SwapChainPanel().ActualOffset().y));
}
_lastHoveredCell = terminalPosition;
const auto newId = _terminal->GetHyperlinkIdAtPosition(terminalPosition);
const auto newInterval = _terminal->GetHyperlinkIntervalFromPosition(terminalPosition);
// If the hyperlink ID changed or the interval changed, trigger a redraw all
// (so this will happen both when we move onto a link and when we move off a link)
if (newId != _lastHoveredId || (newInterval != _lastHoveredInterval))
{
_lastHoveredId = newId;
_lastHoveredInterval = newInterval;
_renderEngine->UpdateHyperlinkHoveredId(newId);
_renderer->UpdateLastHoveredInterval(newInterval);
_renderer->TriggerRedrawAll();
}
}
_UpdateHoveredCell(terminalPosition);
}
else if (ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Touch && _touchAnchor)
else if (_focused && ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Touch && _touchAnchor)
{
const auto contactRect = point.Properties().ContactRect();
winrt::Windows::Foundation::Point newTouchPoint{ contactRect.X, contactRect.Y };
@@ -1549,6 +1557,8 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
return;
}
_RestorePointerCursorHandlers(*this, nullptr);
const auto point = args.GetCurrentPoint(*this);
const auto props = point.Properties();
const TerminalInput::MouseButtonState state{ props.IsLeftButtonPressed(), props.IsMiddleButtonPressed(), props.IsRightButtonPressed() };
@@ -1980,6 +1990,8 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
return;
}
_RestorePointerCursorHandlers(*this, nullptr);
_focused = false;
if (_uiaEngine.get())
@@ -2572,6 +2584,8 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
{
if (!_closing.exchange(true))
{
_RestorePointerCursorHandlers(*this, nullptr);
// Stop accepting new output and state changes before we disconnect everything.
_connection.TerminalOutput(_connectionOutputEventToken);
_connectionStateChangedRevoker.revoke();
@@ -2586,6 +2600,17 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
// closed. We can just do it whenever.
_AsyncCloseConnection();
{
// GH#8734:
// We lock the terminal here to make sure it isn't still being
// used in the connection thread before we destroy the renderer.
// However, we must unlock it again prior to triggering the
// teardown, to avoid the render thread being deadlocked. The
// renderer may be waiting to acquire the terminal lock, while
// we're waiting for the renderer to finish.
auto lock = _terminal->LockForWriting();
}
if (auto localRenderEngine{ std::exchange(_renderEngine, nullptr) })
{
if (auto localRenderer{ std::exchange(_renderer, nullptr) })
@@ -2884,7 +2909,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
// - The Microsoft::Terminal::Core::ControlKeyStates representing the modifier key states.
ControlKeyStates TermControl::_GetPressedModifierKeys() const
{
CoreWindow window = CoreWindow::GetForCurrentThread();
const CoreWindow window = CoreWindow::GetForCurrentThread();
// DONT USE
// != CoreVirtualKeyStates::None
// OR
@@ -3007,7 +3032,8 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
}
// Method Description:
// - Returns the number of clicks that occurred (double and triple click support)
// - Returns the number of clicks that occurred (double and triple click support).
// Every call to this function registers a click.
// Arguments:
// - clickPos: the (x,y) position of a given cursor (i.e.: mouse cursor).
// NOTE: origin (0,0) is top-left.
@@ -3022,13 +3048,15 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
THROW_IF_FAILED(UInt64Sub(clickTime, _lastMouseClickTimestamp, &delta));
if (clickPos != _lastMouseClickPos || delta > _multiClickTimer)
{
// exit early. This is a single click.
_multiClickCounter = 1;
}
else
{
_multiClickCounter++;
}
_lastMouseClickTimestamp = clickTime;
_lastMouseClickPos = clickPos;
return _multiClickCounter;
}
@@ -3267,6 +3295,74 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
return _terminal->GetTaskbarProgress();
}
// Method description:
// - Updates last hovered cell, renders / removes rendering of hyper-link if required
// Arguments:
// - terminalPosition: The terminal position of the pointer
void TermControl::_UpdateHoveredCell(const std::optional<COORD>& terminalPosition)
{
if (terminalPosition == _lastHoveredCell)
{
return;
}
_lastHoveredCell = terminalPosition;
if (terminalPosition.has_value())
{
const auto uri = _terminal->GetHyperlinkAtPosition(*terminalPosition);
if (!uri.empty())
{
// Update the tooltip with the URI
HoveredUri().Text(uri);
// Set the border thickness so it covers the entire cell
const auto charSizeInPixels = CharacterDimensions();
const auto htInDips = charSizeInPixels.Height / SwapChainPanel().CompositionScaleY();
const auto wtInDips = charSizeInPixels.Width / SwapChainPanel().CompositionScaleX();
const Thickness newThickness{ wtInDips, htInDips, 0, 0 };
HyperlinkTooltipBorder().BorderThickness(newThickness);
// Compute the location of the top left corner of the cell in DIPS
const til::size marginsInDips{ til::math::rounding, GetPadding().Left, GetPadding().Top };
const til::point startPos{ terminalPosition->X, terminalPosition->Y };
const til::size fontSize{ _actualFont.GetSize() };
const til::point posInPixels{ startPos * fontSize };
const til::point posInDIPs{ posInPixels / SwapChainPanel().CompositionScaleX() };
const til::point locationInDIPs{ posInDIPs + marginsInDips };
// Move the border to the top left corner of the cell
OverlayCanvas().SetLeft(HyperlinkTooltipBorder(), (locationInDIPs.x() - SwapChainPanel().ActualOffset().x));
OverlayCanvas().SetTop(HyperlinkTooltipBorder(), (locationInDIPs.y() - SwapChainPanel().ActualOffset().y));
}
}
const uint16_t newId = terminalPosition.has_value() ? _terminal->GetHyperlinkIdAtPosition(*terminalPosition) : 0u;
const auto newInterval = terminalPosition.has_value() ? _terminal->GetHyperlinkIntervalFromPosition(*terminalPosition) : std::nullopt;
// If the hyperlink ID changed or the interval changed, trigger a redraw all
// (so this will happen both when we move onto a link and when we move off a link)
if (newId != _lastHoveredId || (newInterval != _lastHoveredInterval))
{
_lastHoveredId = newId;
_lastHoveredInterval = newInterval;
_renderEngine->UpdateHyperlinkHoveredId(newId);
_renderer->UpdateLastHoveredInterval(newInterval);
_renderer->TriggerRedrawAll();
}
}
// Method Description:
// - Handle a mouse exited event, specifically clearing last hovered cell
// and removing selection from hyper link if exists
// Arguments:
// - sender: not used
// - args: event data
void TermControl::_PointerExitedHandler(Windows::Foundation::IInspectable const& /*sender*/, Windows::UI::Xaml::Input::PointerRoutedEventArgs const& /*e*/)
{
_UpdateHoveredCell(std::nullopt);
}
// -------------------------------- WinRT Events ---------------------------------
// Winrt events need a method for adding a callback to the event and removing the callback.
// These macros will define them both for you.

View File

@@ -180,6 +180,8 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
TYPED_EVENT(ConnectionStateChanged, TerminalControl::TermControl, IInspectable);
TYPED_EVENT(Initialized, TerminalControl::TermControl, Windows::UI::Xaml::RoutedEventArgs);
TYPED_EVENT(TabColorChanged, IInspectable, IInspectable);
TYPED_EVENT(HidePointerCursor, IInspectable, IInspectable);
TYPED_EVENT(RestorePointerCursor, IInspectable, IInspectable);
// clang-format on
private:
@@ -238,7 +240,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
std::optional<winrt::Windows::Foundation::Point> _touchAnchor;
// Track the last cell we hovered over (used in pointerMovedHandler)
COORD _lastHoveredCell;
std::optional<COORD> _lastHoveredCell;
// Track the last hyperlink ID we hovered over
uint16_t _lastHoveredId;
@@ -252,6 +254,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
unsigned int _multiClickCounter;
Timestamp _lastMouseClickTimestamp;
std::optional<winrt::Windows::Foundation::Point> _lastMouseClickPos;
std::optional<winrt::Windows::Foundation::Point> _lastMouseClickPosNoSelection;
std::optional<winrt::Windows::Foundation::Point> _singleClickTouchdownPos;
// This field tracks whether the selection has changed meaningfully
// since it was last copied. It's generally used to prevent copyOnSelect
@@ -261,7 +264,8 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
winrt::Windows::UI::Xaml::Controls::SwapChainPanel::LayoutUpdated_revoker _layoutUpdatedRevoker;
void _ApplyUISettings();
void _ApplyUISettings(const IControlSettings&);
void _UpdateSettingsOnUIThread(const IControlSettings& newSettings);
void _UpdateSystemParameterSettings() noexcept;
void _InitializeBackgroundBrush();
winrt::fire_and_forget _BackgroundColorChanged(const COLORREF color);
@@ -275,6 +279,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
void _PointerPressedHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs const& e);
void _PointerMovedHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs const& e);
void _PointerReleasedHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs const& e);
void _PointerExitedHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs const& e);
void _MouseWheelHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs const& e);
void _ScrollbarChangeHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Controls::Primitives::RangeBaseValueChangedEventArgs const& e);
void _GotFocusHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
@@ -335,6 +340,8 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
void _FontInfoHandler(const IInspectable& sender, const FontInfoEventArgs& eventArgs);
winrt::fire_and_forget _AsyncCloseConnection();
void _UpdateHoveredCell(const std::optional<COORD>& terminalPosition);
};
}

View File

@@ -77,6 +77,8 @@ namespace Microsoft.Terminal.TerminalControl
event Windows.Foundation.TypedEventHandler<TermControl, Object> SetTaskbarProgress;
event Windows.Foundation.TypedEventHandler<TermControl, NoticeEventArgs> RaiseNotice;
event Windows.Foundation.TypedEventHandler<Object, Object> WarningBell;
event Windows.Foundation.TypedEventHandler<Object, Object> HidePointerCursor;
event Windows.Foundation.TypedEventHandler<Object, Object> RestorePointerCursor;
event Windows.Foundation.TypedEventHandler<TermControl, Windows.UI.Xaml.RoutedEventArgs> Initialized;
// This is an event handler forwarder for the underlying connection.

View File

@@ -43,7 +43,8 @@
Background="Transparent"
PointerPressed="_PointerPressedHandler"
PointerMoved="_PointerMovedHandler"
PointerReleased="_PointerReleasedHandler">
PointerReleased="_PointerReleasedHandler"
PointerExited="_PointerExitedHandler">
<SwapChainPanel x:Name="SwapChainPanel"
SizeChanged="_SwapChainSizeChanged"

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Windows.CppWinRT" version="2.0.201017.1" targetFramework="native" />
<package id="Microsoft.Windows.CppWinRT" version="2.0.210309.3" targetFramework="native" />
</packages>

View File

@@ -8,6 +8,7 @@ namespace Microsoft.Terminal.TerminalControl
Vintage,
Bar,
Underscore,
DoubleUnderscore,
FilledBox,
EmptyBox
};

View File

@@ -55,6 +55,8 @@ namespace Microsoft::Terminal::Core
virtual bool EnableButtonEventMouseMode(const bool enabled) noexcept = 0;
virtual bool EnableAnyEventMouseMode(const bool enabled) noexcept = 0;
virtual bool EnableAlternateScrollMode(const bool enabled) noexcept = 0;
virtual bool EnableXtermBracketedPasteMode(const bool enabled) noexcept = 0;
virtual bool IsXtermBracketedPasteModeEnabled() const = 0;
virtual bool IsVtInputEnabled() const = 0;

View File

@@ -130,6 +130,9 @@ void Terminal::UpdateSettings(ICoreSettings settings)
case CursorStyle::Vintage:
cursorShape = CursorType::Legacy;
break;
case CursorStyle::DoubleUnderscore:
cursorShape = CursorType::DoubleUnderscore;
break;
default:
case CursorStyle::Bar:
cursorShape = CursorType::VerticalBar;
@@ -330,7 +333,7 @@ void Terminal::UpdateSettings(ICoreSettings settings)
try
{
auto& row = newTextBuffer->GetRowByOffset(::base::ClampSub(proposedTop, 1));
if (row.GetCharRow().WasWrapForced())
if (row.WasWrapForced())
{
proposedTop--;
}

View File

@@ -108,6 +108,8 @@ public:
bool EnableButtonEventMouseMode(const bool enabled) noexcept override;
bool EnableAnyEventMouseMode(const bool enabled) noexcept override;
bool EnableAlternateScrollMode(const bool enabled) noexcept override;
bool EnableXtermBracketedPasteMode(const bool enabled) noexcept override;
bool IsXtermBracketedPasteModeEnabled() const noexcept override;
bool IsVtInputEnabled() const noexcept override;
@@ -249,6 +251,7 @@ private:
bool _snapOnInput;
bool _altGrAliasing;
bool _suppressApplicationTitle;
bool _bracketedPasteMode;
size_t _taskbarState;
size_t _taskbarProgress;

View File

@@ -85,7 +85,7 @@ try
// since we explicitly just moved down a row, clear the wrap status on the
// row we just came from
_buffer->GetRowByOffset(cursorPos.Y).GetCharRow().SetWrapForced(false);
_buffer->GetRowByOffset(cursorPos.Y).SetWrapForced(false);
cursorPos.Y++;
if (withReturn)
@@ -537,6 +537,17 @@ bool Terminal::EnableAlternateScrollMode(const bool enabled) noexcept
return true;
}
bool Terminal::EnableXtermBracketedPasteMode(const bool enabled) noexcept
{
_bracketedPasteMode = enabled;
return true;
}
bool Terminal::IsXtermBracketedPasteModeEnabled() const noexcept
{
return _bracketedPasteMode;
}
bool Terminal::IsVtInputEnabled() const noexcept
{
// We should never be getting this call in Terminal.

View File

@@ -371,6 +371,19 @@ bool TerminalDispatch::EnableAlternateScroll(const bool enabled) noexcept
return true;
}
//Routine Description:
// Enable Bracketed Paste Mode - this changes the behavior of pasting.
// See: https://www.xfree86.org/current/ctlseqs.html#Bracketed%20Paste%20Mode
//Arguments:
// - enabled - true to enable, false to disable.
// Return value:
// True if handled successfully. False otherwise.
bool TerminalDispatch::EnableXtermBracketedPasteMode(const bool enabled) noexcept
{
_terminalApi.EnableXtermBracketedPasteMode(enabled);
return true;
}
bool TerminalDispatch::SetMode(const DispatchTypes::ModeParams param) noexcept
{
return _ModeParamsHelper(param, true);
@@ -461,7 +474,19 @@ bool TerminalDispatch::DoConEmuAction(const std::wstring_view string) noexcept
{
if (parts.size() >= 2)
{
return _terminalApi.SetWorkingDirectory(til::at(parts, 1));
const auto path = til::at(parts, 1);
// The path should be surrounded with '"' according to the documentation of ConEmu.
// An example: 9;"D:/"
if (path.at(0) == L'"' && path.at(path.size() - 1) == L'"' && path.size() >= 3)
{
return _terminalApi.SetWorkingDirectory(path.substr(1, path.size() - 2));
}
else
{
// If we fail to find the surrounding quotation marks, we'll give the path a try anyway.
// ConEmu also does this.
return _terminalApi.SetWorkingDirectory(path);
}
}
}
@@ -511,6 +536,9 @@ bool TerminalDispatch::_ModeParamsHelper(const DispatchTypes::ModeParams param,
case DispatchTypes::ModeParams::ATT610_StartCursorBlink:
success = EnableCursorBlinking(enable);
break;
case DispatchTypes::ModeParams::XTERM_BracketedPasteMode:
success = EnableXtermBracketedPasteMode(enable);
break;
case DispatchTypes::ModeParams::W32IM_Win32InputMode:
success = EnableWin32InputMode(enable);
break;

View File

@@ -63,6 +63,7 @@ public:
bool EnableButtonEventMouseMode(const bool enabled) noexcept override; // ?1002
bool EnableAnyEventMouseMode(const bool enabled) noexcept override; // ?1003
bool EnableAlternateScroll(const bool enabled) noexcept override; // ?1007
bool EnableXtermBracketedPasteMode(const bool enabled) noexcept override; // ?2004
bool SetMode(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::ModeParams /*param*/) noexcept override; // DECSET
bool ResetMode(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::ModeParams /*param*/) noexcept override; // DECRST

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Windows.CppWinRT" version="2.0.201017.1" targetFramework="native" />
<package id="Microsoft.Windows.CppWinRT" version="2.0.210309.3" targetFramework="native" />
</packages>

View File

@@ -129,7 +129,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
// Surprisingly, though this is called every time we navigate to the page,
// the list does not keep growing on each navigation.
const auto& colorSchemeMap{ _State.Globals().ColorSchemes() };
const auto& colorSchemeMap{ _State.Settings().GlobalSettings().ColorSchemes() };
for (const auto& pair : colorSchemeMap)
{
_ColorSchemeList.Append(pair.Value());
@@ -174,7 +174,10 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
void ColorSchemes::DeleteConfirmation_Click(IInspectable const& /*sender*/, RoutedEventArgs const& /*e*/)
{
const auto schemeName{ CurrentColorScheme().Name() };
_State.Globals().RemoveColorScheme(schemeName);
_State.Settings().GlobalSettings().RemoveColorScheme(schemeName);
// This ensures that the JSON is updated with "Campbell", because the color scheme was deleted
_State.Settings().UpdateColorSchemeReferences(schemeName, L"Campbell");
const auto removedSchemeIndex{ ColorSchemeComboBox().SelectedIndex() };
if (static_cast<uint32_t>(removedSchemeIndex) < _ColorSchemeList.Size() - 1)
@@ -194,11 +197,11 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
void ColorSchemes::AddNew_Click(IInspectable const& /*sender*/, RoutedEventArgs const& /*e*/)
{
// Give the new scheme a distinct name
const hstring schemeName{ fmt::format(L"Color Scheme {}", _State.Globals().ColorSchemes().Size() + 1) };
const hstring schemeName{ fmt::format(L"Color Scheme {}", _State.Settings().GlobalSettings().ColorSchemes().Size() + 1) };
Model::ColorScheme scheme{ schemeName };
// Add the new color scheme
_State.Globals().AddColorScheme(scheme);
_State.Settings().GlobalSettings().AddColorScheme(scheme);
// Update current page
_ColorSchemeList.Append(scheme);
@@ -227,6 +230,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
void ColorSchemes::RenameCancel_Click(IInspectable const& /*sender*/, RoutedEventArgs const& /*e*/)
{
IsRenaming(false);
RenameErrorTip().IsOpen(false);
}
void ColorSchemes::NameBox_PreviewKeyDown(IInspectable const& /*sender*/, winrt::Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e)
@@ -239,12 +243,35 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
else if (e.OriginalKey() == winrt::Windows::System::VirtualKey::Escape)
{
IsRenaming(false);
RenameErrorTip().IsOpen(false);
e.Handled(true);
}
}
void ColorSchemes::_RenameCurrentScheme(hstring newName)
{
// check if different name is already in use
const auto oldName{ CurrentColorScheme().Name() };
if (newName != oldName && _State.Settings().GlobalSettings().ColorSchemes().HasKey(newName))
{
// open the error tip
RenameErrorTip().Target(NameBox());
RenameErrorTip().IsOpen(true);
// focus the name box
NameBox().Focus(FocusState::Programmatic);
NameBox().SelectAll();
return;
}
// update the settings model
CurrentColorScheme().Name(newName);
_State.Settings().GlobalSettings().RemoveColorScheme(oldName);
_State.Settings().GlobalSettings().AddColorScheme(CurrentColorScheme());
_State.Settings().UpdateColorSchemeReferences(oldName, newName);
// update the UI
RenameErrorTip().IsOpen(false);
CurrentColorScheme().Name(newName);
IsRenaming(false);

View File

@@ -13,10 +13,10 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
struct ColorSchemesPageNavigationState : ColorSchemesPageNavigationStateT<ColorSchemesPageNavigationState>
{
public:
ColorSchemesPageNavigationState(const Model::GlobalAppSettings& settings) :
_Globals{ settings } {}
ColorSchemesPageNavigationState(const Model::CascadiaSettings& settings) :
_Settings{ settings } {}
GETSET_PROPERTY(Model::GlobalAppSettings, Globals, nullptr);
GETSET_PROPERTY(Model::CascadiaSettings, Settings, nullptr);
GETSET_PROPERTY(winrt::hstring, LastSelectedScheme, L"");
};

View File

@@ -6,7 +6,7 @@ namespace Microsoft.Terminal.Settings.Editor
runtimeclass ColorSchemesPageNavigationState
{
Microsoft.Terminal.Settings.Model.GlobalAppSettings Globals;
Microsoft.Terminal.Settings.Model.CascadiaSettings Settings;
String LastSelectedScheme;
};

View File

@@ -6,6 +6,7 @@ the MIT License. See LICENSE in the project root for license information. -->
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Microsoft.Terminal.Settings.Editor"
xmlns:model="using:Microsoft.Terminal.Settings.Model"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
@@ -24,7 +25,7 @@ the MIT License. See LICENSE in the project root for license information. -->
</Style>
<Style x:Key="ColorHeaderStyle" TargetType="TextBlock">
<Setter Property="Margin" Value="0,0,0,4"/>
<Setter Property="Margin" Value="0,0,0,5"/>
</Style>
<Style TargetType="Button" BasedOn="{StaticResource BaseButtonStyle}">
@@ -65,8 +66,7 @@ the MIT License. See LICENSE in the project root for license information. -->
<StackPanel Orientation="Horizontal"
Grid.Row="0"
Grid.Column="0"
Grid.ColumnSpan="2"
Margin="{StaticResource StandardControlSpacing}">
Grid.ColumnSpan="2">
<StackPanel Orientation="Horizontal"
Visibility="{x:Bind IsRenaming, Converter={StaticResource InvertedBooleanToVisibilityConverter}, Mode=OneWay}">
@@ -86,27 +86,45 @@ the MIT License. See LICENSE in the project root for license information. -->
<!--Rename Button-->
<!--Bind IsEnabled to prevent a the color scheme from returning from the dead-->
<Button x:Uid="Rename"
Style="{StaticResource BrowseButtonStyle}"
Style="{StaticResource SmallButtonStyle}"
Click="Rename_Click"
IsEnabled="{x:Bind CanDeleteCurrentScheme, Mode=OneWay}">
<FontIcon Glyph="&#xE8AC;"/>
<StackPanel Orientation="Horizontal">
<FontIcon Glyph="&#xE8AC;"
FontSize="{StaticResource StandardIconSize}"/>
</StackPanel>
</Button>
</StackPanel>
<StackPanel Orientation="Horizontal"
Visibility="{x:Bind IsRenaming, Mode=OneWay}">
<!--Shown when color scheme name is already in use-->
<muxc:TeachingTip x:Name="RenameErrorTip"
x:Uid="ColorScheme_RenameErrorTip"/>
<!--Name text box-->
<TextBox x:Name="NameBox"
Style="{StaticResource TextBoxSettingStyle}"
PreviewKeyDown="NameBox_PreviewKeyDown"/>
<!--Accept rename button-->
<Button x:Uid="RenameAccept"
Style="{StaticResource AccentBrowseButtonStyle}"
Style="{StaticResource AccentSmallButtonStyle}"
Click="RenameAccept_Click">
<FontIcon Glyph="&#xE8FB;"/>
<StackPanel Orientation="Horizontal">
<FontIcon Glyph="&#xE8FB;"
FontSize="{StaticResource StandardIconSize}"/>
</StackPanel>
</Button>
<!--Cancel rename button-->
<Button x:Uid="RenameCancel"
Style="{StaticResource BrowseButtonStyle}"
Style="{StaticResource SmallButtonStyle}"
Click="RenameCancel_Click">
<FontIcon Glyph="&#xE711;"/>
<StackPanel Orientation="Horizontal">
<FontIcon Glyph="&#xE711;"
FontSize="{StaticResource StandardIconSize}"/>
</StackPanel>
</Button>
</StackPanel>
@@ -115,10 +133,9 @@ the MIT License. See LICENSE in the project root for license information. -->
Style="{StaticResource BrowseButtonStyle}">
<StackPanel Orientation="Horizontal">
<FontIcon Glyph="&#xE710;"
FontSize="15"/>
FontSize="{StaticResource StandardIconSize}"/>
<TextBlock x:Uid="ColorScheme_AddNewButton"
Margin="10,0,0,0"
FontSize="15"/>
Style="{StaticResource IconButtonTextBlockStyle}"/>
</StackPanel>
</Button>
</StackPanel>
@@ -127,7 +144,8 @@ the MIT License. See LICENSE in the project root for license information. -->
<ItemsControl x:Name="ColorTableControl"
ItemsSource="{x:Bind CurrentColorTable, Mode=OneWay}"
Grid.Row="1"
Grid.Column="0">
Grid.Column="0"
Style="{StaticResource ItemsControlStyle}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
@@ -173,7 +191,8 @@ the MIT License. See LICENSE in the project root for license information. -->
<!-- Additional Colors (Right Column) -->
<ItemsControl Grid.Row="1"
Grid.Column="1">
Grid.Column="1"
Style="{StaticResource ItemsControlStyle}">
<StackPanel Style="{StaticResource ColorStackPanelStyle}">
<TextBlock x:Uid="ColorScheme_Foreground"
Style="{StaticResource ColorHeaderStyle}"/>
@@ -295,11 +314,10 @@ the MIT License. See LICENSE in the project root for license information. -->
<StackPanel Grid.Row="2"
Grid.Column="0"
Grid.ColumnSpan="2"
Margin="{StaticResource StandardControlSpacing}">
Style="{StaticResource PivotStackStyle}">
<Button x:Name="DeleteButton"
Style="{StaticResource BaseButtonStyle}"
IsEnabled="{x:Bind CanDeleteCurrentScheme, Mode=OneWay}"
Margin="0,0,0,10">
Style="{StaticResource DeleteButtonStyle}">
<Button.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
@@ -332,11 +350,9 @@ the MIT License. See LICENSE in the project root for license information. -->
</Button.Resources>
<Button.Content>
<StackPanel Orientation="Horizontal">
<FontIcon Glyph="&#xE74D;"
FontSize="{StaticResource StandardFontSize}"/>
<FontIcon Glyph="&#xE74D;"/>
<TextBlock x:Uid="ColorScheme_DeleteButton"
FontSize="{StaticResource StandardFontSize}"
Margin="10,0,0,0"/>
Style="{StaticResource IconButtonTextBlockStyle}"/>
</StackPanel>
</Button.Content>
<Button.Flyout>
@@ -344,8 +360,7 @@ the MIT License. See LICENSE in the project root for license information. -->
<StackPanel>
<TextBlock x:Uid="ColorScheme_DeleteConfirmationMessage"
Style="{StaticResource CustomFlyoutTextStyle}"/>
<Button x:Uid="ColorScheme_DeleteConfirmationButton"
Style="{StaticResource BaseButtonStyle}"
<Button x:Uid="ColorScheme_DeleteConfirmationButton"
Click="DeleteConfirmation_Click"/>
</StackPanel>
</Flyout>

View File

@@ -3,54 +3,42 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls">
<x:Double x:Key="StandardFontSize">15.0</x:Double>
<Thickness x:Key="StandardIndentMargin">20,0,0,0</Thickness>
<Thickness x:Key="StandardControlSpacing">0,0,0,20</Thickness>
<x:Double x:Key="StandardIconSize">14.0</x:Double>
<Thickness x:Key="StandardIndentMargin">13,0,0,0</Thickness>
<Thickness x:Key="StandardControlMargin">0,24,0,0</Thickness>
<x:Double x:Key="StandardBoxMinWidth">250</x:Double>
<Thickness x:Key="PivotIndentMargin">10,0,0,0</Thickness>
<Thickness x:Key="PivotStackPanelMargin">0,10,0,0</Thickness>
<!-- This is for easier transition to the SettingsContainer control.
The SettingsContainer will wrap a setting with inheritance UI.-->
<Style x:Key="SettingContainerStyle" TargetType="ContentPresenter">
<Setter Property="Padding" Value="{StaticResource StandardControlSpacing}"/>
<Setter Property="Margin" Value="{StaticResource StandardControlMargin}"/>
</Style>
<!-- This is for styling the entire items control used on the
color schemes page-->
<Style x:Key="ItemsControlStyle" TargetType="ItemsControl">
<Setter Property="Margin" Value="{StaticResource StandardControlMargin}"/>
</Style>
<!--Used to stack a group of settings-->
<Style x:Key="SettingsStackStyle" TargetType="StackPanel">
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="Margin" Value="{StaticResource StandardIndentMargin}"/>
<Setter Property="Margin" Value="13,0,0,48"/>
</Style>
<!--Radio Button-->
<Style x:Key="RadioButtonsSettingStyle" TargetType="muxc:RadioButtons">
<Setter Property="FontSize" Value="{StaticResource StandardFontSize}"/>
<Setter Property="ToolTipService.Placement" Value="Mouse"/>
</Style>
<Style x:Key="RadioButtonSettingStyle" TargetType="RadioButton" BasedOn="{StaticResource DefaultRadioButtonStyle}">
<Setter Property="FontSize" Value="{StaticResource StandardFontSize}"/>
<Setter Property="ToolTipService.Placement" Value="Mouse"/>
</Style>
<!--Check Box-->
<Style x:Key="CheckBoxSettingStyle" TargetType="CheckBox" BasedOn="{StaticResource DefaultCheckBoxStyle}">
<Setter Property="FontSize" Value="{StaticResource StandardFontSize}"/>
<Setter Property="ToolTipService.Placement" Value="Mouse"/>
<!--Used to stack a group of settings inside a pivot-->
<Style x:Key="PivotStackStyle" TargetType="StackPanel">
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="Margin" Value="0,0,0,48"/>
</Style>
<!--Combo Box-->
<Style x:Key="ComboBoxSettingStyle" TargetType="ComboBox" BasedOn="{StaticResource DefaultComboBoxStyle}">
<Setter Property="FontSize" Value="{StaticResource StandardFontSize}"/>
<Setter Property="ToolTipService.Placement" Value="Mouse"/>
<Setter Property="MinWidth" Value="{StaticResource StandardBoxMinWidth}"/>
</Style>
<!--Text Box-->
<Style x:Key="TextBoxSettingStyle" TargetType="TextBox" BasedOn="{StaticResource DefaultTextBoxStyle}">
<Setter Property="FontSize" Value="{StaticResource StandardFontSize}"/>
<Setter Property="ToolTipService.Placement" Value="Mouse"/>
<Setter Property="Width" Value="{StaticResource StandardBoxMinWidth}"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="TextWrapping" Value="Wrap"/>
@@ -58,77 +46,76 @@
<!--Used to create a header for a control-->
<Style x:Key="CustomSettingHeaderStyle" TargetType="TextBlock">
<Setter Property="FontSize" Value="{StaticResource StandardFontSize}"/>
<Setter Property="Margin" Value="0,0,0,4"/>
</Style>
<!-- Used to create a header for a group of settings -->
<Style x:Key="GroupingHeader" TargetType="TextBlock" BasedOn="{StaticResource SubtitleTextBlockStyle}">
<Setter Property="Margin" Value="0,20,0,10"/>
</Style>
<!--Used for disclaimers-->
<Style x:Key="DisclaimerStyle" TargetType="TextBlock">
<Setter Property="FontSize" Value="{StaticResource StandardFontSize}"/>
<Setter Property="FontStyle" Value="Italic"/>
<Setter Property="TextWrapping" Value="WrapWholeWords"/>
</Style>
<!--Used for flyout messages-->
<Style x:Key="CustomFlyoutTextStyle" TargetType="TextBlock" BasedOn="{StaticResource BaseTextBlockStyle}">
<Setter Property="FontSize" Value="{StaticResource StandardFontSize}"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Margin" Value="0,0,0,12"/>
<Setter Property="Margin" Value="0,0,0,10"/>
</Style>
<!--Number Box-->
<Style x:Key="NumberBoxSettingStyle" TargetType="muxc:NumberBox">
<Setter Property="FontSize" Value="{StaticResource StandardFontSize}"/>
<Setter Property="ToolTipService.Placement" Value="Mouse"/>
<Setter Property="SpinButtonPlacementMode" Value="Compact"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
</Style>
<!--Button-Related Styling-->
<Style x:Key="BaseButtonStyle" TargetType="Button" BasedOn="{StaticResource DefaultButtonStyle}">
<Setter Property="FontSize" Value="{StaticResource StandardFontSize}"/>
<Setter Property="ToolTipService.Placement" Value="Mouse"/>
<Setter Property="VerticalAlignment" Value="Bottom"/>
</Style>
<Style x:Key="BrowseButtonStyle" TargetType="Button" BasedOn="{StaticResource BaseButtonStyle}">
<Setter Property="Margin" Value="10,0,0,0"/>
<Setter Property="VerticalAlignment" Value="Bottom"/>
<Setter Property="Height" Value="33"/>
</Style>
<Style x:Key="DeleteButtonStyle" TargetType="Button" BasedOn="{StaticResource BaseButtonStyle}">
<Setter Property="Margin" Value="0,0,0,10"/>
</Style>
<Style x:Key="SmallButtonStyle" TargetType="Button" BasedOn="{StaticResource BrowseButtonStyle}">
<Setter Property="Height" Value="33"/>
<Setter Property="Width" Value="33"/>
</Style>
<Style x:Key="AccentBrowseButtonStyle" TargetType="Button" BasedOn="{StaticResource AccentButtonStyle}">
<Setter Property="FontSize" Value="{StaticResource StandardFontSize}"/>
<Setter Property="ToolTipService.Placement" Value="Mouse"/>
<Setter Property="Margin" Value="10,0,0,0"/>
<Setter Property="VerticalAlignment" Value="Bottom"/>
</Style>
<!--Slider-Related Styling-->
<Style x:Key="SliderSettingStyle" TargetType="Slider" BasedOn="{StaticResource DefaultSliderStyle}">
<Setter Property="FontSize" Value="{StaticResource StandardFontSize}"/>
<Setter Property="ToolTipService.Placement" Value="Mouse"/>
<Style x:Key="AccentSmallButtonStyle" TargetType="Button" BasedOn="{StaticResource AccentButtonStyle}">
<Setter Property="Margin" Value="10,0,0,0"/>
<Setter Property="VerticalAlignment" Value="Bottom"/>
<Setter Property="Height" Value="33"/>
<Setter Property="Width" Value="33"/>
</Style>
<Style x:Key="IconButtonTextBlockStyle" TargetType="TextBlock">
<Setter Property="Margin" Value="10,0,0,0"/>
</Style>
<!--Slider-Related Styling-->
<Style x:Key="SliderValueLabelStyle" TargetType="TextBlock">
<Setter Property="Width" Value="35"/>
<Setter Property="Margin" Value="10,0,0,20"/>
<Setter Property="FontSize" Value="15"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="ToolTipService.Placement" Value="Mouse"/>
<Setter Property="Margin" Value="5,0,0,0"/>
</Style>
<Style x:Key="SliderHeaderStyle" TargetType="TextBlock" BasedOn="{StaticResource CustomSettingHeaderStyle}">
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="ToolTipService.Placement" Value="Mouse"/>
</Style>
<Style x:Key="CustomSliderControlGridStyle" TargetType="Grid">
<Setter Property="Width" Value="300"/>
<Setter Property="Width" Value="{StaticResource StandardBoxMinWidth}"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
</Style>
</ResourceDictionary>

View File

@@ -39,6 +39,11 @@ namespace Microsoft.Terminal.Settings.Editor
StringIsEmptyConverter();
};
runtimeclass PaddingConverter : [default] Windows.UI.Xaml.Data.IValueConverter
{
PaddingConverter();
};
runtimeclass StringIsNotDesktopConverter : [default] Windows.UI.Xaml.Data.IValueConverter
{
StringIsNotDesktopConverter();

View File

@@ -17,8 +17,7 @@ the MIT License. See LICENSE in the project root for license information. -->
</ResourceDictionary.MergedDictionaries>
<DataTemplate x:DataType="local:EnumEntry" x:Key="EnumRadioButtonTemplate">
<RadioButton Content="{x:Bind EnumName, Mode=OneWay}"
Style="{StaticResource RadioButtonSettingStyle}"/>
<RadioButton Content="{x:Bind EnumName, Mode=OneWay}"/>
</DataTemplate>
</ResourceDictionary>
</Page.Resources>
@@ -26,40 +25,36 @@ the MIT License. See LICENSE in the project root for license information. -->
<ScrollViewer>
<StackPanel Style="{StaticResource SettingsStackStyle}">
<!--Theme-->
<ContentPresenter Style="{StaticResource SettingContainerStyle}">
<ContentPresenter Style="{StaticResource SettingContainerStyle}"
Margin="0">
<muxc:RadioButtons x:Uid="Globals_Theme"
SelectedItem="{x:Bind CurrentTheme, Mode=TwoWay}"
ItemsSource="{x:Bind ThemeList, Mode=OneWay}"
ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
Style="{StaticResource RadioButtonsSettingStyle}"/>
ItemTemplate="{StaticResource EnumRadioButtonTemplate}"/>
</ContentPresenter>
<!--Always show tabs-->
<ContentPresenter Style="{StaticResource SettingContainerStyle}">
<CheckBox x:Uid="Globals_AlwaysShowTabs"
IsChecked="{x:Bind State.Globals.AlwaysShowTabs, Mode=TwoWay}"
Style="{StaticResource CheckBoxSettingStyle}"/>
<ToggleSwitch x:Uid="Globals_AlwaysShowTabs"
IsOn="{x:Bind State.Globals.AlwaysShowTabs, Mode=TwoWay}"/>
</ContentPresenter>
<!--Show Titlebar-->
<ContentPresenter Style="{StaticResource SettingContainerStyle}">
<CheckBox x:Uid="Globals_ShowTitlebar"
IsChecked="{x:Bind State.Globals.ShowTabsInTitlebar, Mode=TwoWay}"
Style="{StaticResource CheckBoxSettingStyle}"/>
<ToggleSwitch x:Uid="Globals_ShowTitlebar"
IsOn="{x:Bind State.Globals.ShowTabsInTitlebar, Mode=TwoWay}"/>
</ContentPresenter>
<!--Show Title in Titlebar-->
<ContentPresenter Style="{StaticResource SettingContainerStyle}">
<CheckBox x:Uid="Globals_ShowTitleInTitlebar"
IsChecked="{x:Bind State.Globals.ShowTitleInTitlebar, Mode=TwoWay}"
Style="{StaticResource CheckBoxSettingStyle}"/>
<ToggleSwitch x:Uid="Globals_ShowTitleInTitlebar"
IsOn="{x:Bind State.Globals.ShowTitleInTitlebar, Mode=TwoWay}"/>
</ContentPresenter>
<!--Always on Top-->
<ContentPresenter Style="{StaticResource SettingContainerStyle}">
<CheckBox x:Uid="Globals_AlwaysOnTop"
IsChecked="{x:Bind State.Globals.AlwaysOnTop, Mode=TwoWay}"
Style="{StaticResource CheckBoxSettingStyle}"/>
<ToggleSwitch x:Uid="Globals_AlwaysOnTop"
IsOn="{x:Bind State.Globals.AlwaysOnTop, Mode=TwoWay}"/>
</ContentPresenter>
<!--Tab Width Mode-->
@@ -67,15 +62,13 @@ the MIT License. See LICENSE in the project root for license information. -->
<muxc:RadioButtons x:Uid="Globals_TabWidthMode"
SelectedItem="{x:Bind CurrentTabWidthMode, Mode=TwoWay}"
ItemsSource="{x:Bind TabWidthModeList, Mode=OneWay}"
ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
Style="{StaticResource RadioButtonsSettingStyle}"/>
ItemTemplate="{StaticResource EnumRadioButtonTemplate}"/>
</ContentPresenter>
<!--Disable Animations-->
<ContentPresenter Style="{StaticResource SettingContainerStyle}">
<CheckBox x:Uid="Globals_DisableAnimations"
IsChecked="{x:Bind State.Globals.DisableAnimations, Mode=TwoWay}"
Style="{StaticResource CheckBoxSettingStyle}"/>
<ToggleSwitch x:Uid="Globals_DisableAnimations"
IsOn="{x:Bind State.Globals.DisableAnimations, Mode=TwoWay}"/>
</ContentPresenter>
</StackPanel>
</ScrollViewer>

View File

@@ -17,8 +17,7 @@ the MIT License. See LICENSE in the project root for license information. -->
</ResourceDictionary.MergedDictionaries>
<DataTemplate x:DataType="local:EnumEntry" x:Key="EnumRadioButtonTemplate">
<RadioButton Content="{x:Bind EnumName, Mode=OneWay}"
Style="{StaticResource RadioButtonSettingStyle}"/>
<RadioButton Content="{x:Bind EnumName, Mode=OneWay}"/>
</DataTemplate>
</ResourceDictionary>
</Page.Resources>
@@ -26,10 +25,10 @@ the MIT License. See LICENSE in the project root for license information. -->
<ScrollViewer>
<StackPanel Style="{StaticResource SettingsStackStyle}">
<!--Copy On Select-->
<ContentPresenter Style="{StaticResource SettingContainerStyle}">
<CheckBox x:Uid="Globals_CopyOnSelect"
IsChecked="{x:Bind State.Globals.CopyOnSelect, Mode=TwoWay}"
Style="{StaticResource CheckBoxSettingStyle}"/>
<ContentPresenter Style="{StaticResource SettingContainerStyle}"
Margin="0">
<ToggleSwitch x:Uid="Globals_CopyOnSelect"
IsOn="{x:Bind State.Globals.CopyOnSelect, Mode=TwoWay}"/>
</ContentPresenter>
<!--Copy Format-->
@@ -37,8 +36,7 @@ the MIT License. See LICENSE in the project root for license information. -->
<muxc:RadioButtons x:Uid="Globals_CopyFormat"
ItemsSource="{x:Bind CopyFormatList, Mode=OneWay}"
SelectedItem="{x:Bind CurrentCopyFormat, Mode=TwoWay}"
ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
Style="{StaticResource RadioButtonsSettingStyle}"/>
ItemTemplate="{StaticResource EnumRadioButtonTemplate}"/>
</ContentPresenter>
<!--Word Delimiters-->
@@ -50,18 +48,16 @@ the MIT License. See LICENSE in the project root for license information. -->
<!--Snap On Resize-->
<ContentPresenter Style="{StaticResource SettingContainerStyle}">
<CheckBox x:Uid="Globals_SnapToGridOnResize"
IsChecked="{x:Bind State.Globals.SnapToGridOnResize, Mode=TwoWay}"
Style="{StaticResource CheckBoxSettingStyle}"/>
<ToggleSwitch x:Uid="Globals_SnapToGridOnResize"
IsOn="{x:Bind State.Globals.SnapToGridOnResize, Mode=TwoWay}"/>
</ContentPresenter>
<!--Tab Switcher Mode-->
<ContentPresenter Style="{StaticResource SettingContainerStyle}">
<muxc:RadioButtons x:Uid="Globals_TabSwitcherMode"
SelectedItem="{x:Bind CurrentTabSwitcherMode}"
SelectedItem="{x:Bind CurrentTabSwitcherMode, Mode=TwoWay}"
ItemsSource="{x:Bind TabSwitcherModeList}"
ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
Style="{StaticResource RadioButtonsSettingStyle}"/>
ItemTemplate="{StaticResource EnumRadioButtonTemplate}"/>
</ContentPresenter>
</StackPanel>
</ScrollViewer>

View File

@@ -6,7 +6,6 @@
#include "Launch.g.h"
#include "LaunchPageNavigationState.g.h"
#include "Utils.h"
#include "../CommandlineArgs/AppCommandlineArgs.h"
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
@@ -32,9 +31,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
GETSET_PROPERTY(Editor::LaunchPageNavigationState, State, nullptr);
GETSET_BINDABLE_ENUM_SETTING(LaunchMode, Model::LaunchMode, State().Settings().GlobalSettings, LaunchMode);
private:
::Microsoft::Terminal::CommandlineArgs::AppCommandlineArgs argParser;
};
}

View File

@@ -18,34 +18,40 @@ the MIT License. See LICENSE in the project root for license information. -->
</ResourceDictionary.MergedDictionaries>
<DataTemplate x:DataType="local:EnumEntry" x:Key="EnumRadioButtonTemplate">
<RadioButton Content="{x:Bind EnumName, Mode=OneWay}"
Style="{StaticResource RadioButtonSettingStyle}"/>
<RadioButton Content="{x:Bind EnumName, Mode=OneWay}"/>
</DataTemplate>
<SettingsModel:IconPathConverter x:Key="IconSourceConverter"/>
<Style x:Key="LaunchSizeNumberBoxStyle" TargetType="muxc:NumberBox" BasedOn="{StaticResource NumberBoxSettingStyle}">
<Setter Property="SmallChange" Value="1"/>
<Setter Property="LargeChange" Value="10"/>
<Setter Property="Minimum" Value="1"/>
</Style>
</ResourceDictionary>
</Page.Resources>
<ScrollViewer>
<StackPanel Style="{StaticResource SettingsStackStyle}">
<!--Default Profile-->
<ContentPresenter Style="{StaticResource SettingContainerStyle}">
<ComboBox x:Uid="Globals_DefaultProfile"
<StackPanel>
<StackPanel Style="{StaticResource SettingsStackStyle}">
<!--Default Profile-->
<ContentPresenter Style="{StaticResource SettingContainerStyle}"
Margin="0">
<ComboBox x:Uid="Globals_DefaultProfile"
x:Name="DefaultProfile"
ItemsSource="{x:Bind State.Settings.AllProfiles, Mode=OneWay}"
SelectedItem="{x:Bind CurrentDefaultProfile, Mode=TwoWay}"
Style="{StaticResource ComboBoxSettingStyle}">
<ComboBox.ItemTemplate>
<DataTemplate x:DataType="SettingsModel:Profile">
<Grid HorizontalAlignment="Stretch" ColumnSpacing="8">
<ComboBox.ItemTemplate>
<DataTemplate x:DataType="SettingsModel:Profile">
<Grid HorizontalAlignment="Stretch" ColumnSpacing="8">
<Grid.ColumnDefinitions>
<!-- icon -->
<ColumnDefinition Width="16"/>
<!-- profile name -->
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.ColumnDefinitions>
<!-- icon -->
<ColumnDefinition Width="16"/>
<!-- profile name -->
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<IconSourceElement
<IconSourceElement
Grid.Column="0"
Width="16"
Height="16"
@@ -53,80 +59,50 @@ the MIT License. See LICENSE in the project root for license information. -->
Mode=OneWay,
Converter={StaticResource IconSourceConverter}}"/>
<TextBlock Grid.Column="1"
Text="{x:Bind Name}"
FontSize="{StaticResource StandardFontSize}"/>
<TextBlock Grid.Column="1"
Text="{x:Bind Name}"/>
</Grid>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</ContentPresenter>
</Grid>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</ContentPresenter>
<!--Start on User Login-->
<ContentPresenter Style="{StaticResource SettingContainerStyle}">
<CheckBox x:Uid="Globals_StartOnUserLogin"
IsChecked="{x:Bind State.Settings.GlobalSettings.StartOnUserLogin, Mode=TwoWay}"
Style="{StaticResource CheckBoxSettingStyle}"/>
</ContentPresenter>
<!--Start on User Login-->
<ContentPresenter Style="{StaticResource SettingContainerStyle}">
<ToggleSwitch x:Uid="Globals_StartOnUserLogin"
IsOn="{x:Bind State.Settings.GlobalSettings.StartOnUserLogin, Mode=TwoWay}"/>
</ContentPresenter>
<!--Launch Mode-->
<ContentPresenter Style="{StaticResource SettingContainerStyle}">
<muxc:RadioButtons x:Uid="Globals_LaunchMode"
SelectedItem="{x:Bind CurrentLaunchMode}"
<!--Launch Mode-->
<ContentPresenter Style="{StaticResource SettingContainerStyle}">
<muxc:RadioButtons x:Uid="Globals_LaunchMode"
SelectedItem="{x:Bind CurrentLaunchMode, Mode=TwoWay}"
ItemsSource="{x:Bind LaunchModeList}"
ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
Style="{StaticResource RadioButtonsSettingStyle}"/>
</ContentPresenter>
ItemTemplate="{StaticResource EnumRadioButtonTemplate}"/>
</ContentPresenter>
</StackPanel>
<!--Launch Size-->
<ContentPresenter Style="{StaticResource SettingContainerStyle}">
<Grid>
<Grid.Resources>
<Style x:Key="LaunchSizeSubHeaderStyle" TargetType="TextBlock">
<Setter Property="FontSize" Value="{StaticResource StandardFontSize}"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="Margin" Value="0,0,5,0"/>
</Style>
<Style x:Key="LaunchSizeNumberBoxStyle" TargetType="muxc:NumberBox" BasedOn="{StaticResource NumberBoxSettingStyle}">
<Setter Property="SmallChange" Value="1"/>
<Setter Property="LargeChange" Value="10"/>
<Setter Property="Minimum" Value="1"/>
</Style>
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<StackPanel Style="{StaticResource SettingsStackStyle}">
<!--Header-->
<TextBlock x:Uid="Globals_LaunchSize"
Style="{StaticResource SubtitleTextBlockStyle}"/>
<!--Header-->
<TextBlock x:Uid="Globals_LaunchSize"
Grid.Row="0" Grid.Column="0"
Grid.ColumnSpan="2"
Style="{StaticResource CustomSettingHeaderStyle}"/>
<!--Columns-->
<StackPanel Orientation="Horizontal"
Grid.Row="1" Grid.Column="0"
Margin="0,0,10,0">
<TextBlock x:Uid="Globals_InitialCols" Style="{StaticResource LaunchSizeSubHeaderStyle}"/>
<muxc:NumberBox Value="{x:Bind State.Settings.GlobalSettings.InitialCols, Mode=TwoWay}"
Style="{StaticResource LaunchSizeNumberBoxStyle}"/>
</StackPanel>
<!--Rows-->
<StackPanel Orientation="Horizontal"
Grid.Row="1" Grid.Column="1">
<TextBlock x:Uid="Globals_InitialRows" Style="{StaticResource LaunchSizeSubHeaderStyle}"/>
<muxc:NumberBox Value="{x:Bind State.Settings.GlobalSettings.InitialRows, Mode=TwoWay}"
Style="{StaticResource LaunchSizeNumberBoxStyle}"/>
</StackPanel>
</Grid>
</ContentPresenter>
<!--Columns-->
<ContentPresenter Style="{StaticResource SettingContainerStyle}"
Margin="0">
<muxc:NumberBox x:Uid="Globals_InitialCols"
Value="{x:Bind State.Settings.GlobalSettings.InitialCols, Mode=TwoWay}"
Style="{StaticResource LaunchSizeNumberBoxStyle}"/>
</ContentPresenter>
<!--Rows-->
<ContentPresenter Style="{StaticResource SettingContainerStyle}">
<muxc:NumberBox x:Uid="Globals_InitialRows"
Value="{x:Bind State.Settings.GlobalSettings.InitialRows, Mode=TwoWay}"
Style="{StaticResource LaunchSizeNumberBoxStyle}"/>
</ContentPresenter>
</StackPanel>
</StackPanel>
</ScrollViewer>
</Page>

View File

@@ -50,19 +50,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
_InitializeProfilesList();
_colorSchemesNavState = winrt::make<ColorSchemesPageNavigationState>(_settingsClone.GlobalSettings());
// We have to provide _some_ profile in the profile nav state, so just
// hook it up with the base for now. It'll get updated when we actually
// navigate to a profile.
auto profileVM{ _viewModelForProfile(_settingsClone.ProfileDefaults()) };
profileVM.IsBaseLayer(true);
_profilesNavState = winrt::make<ProfilePageNavigationState>(profileVM,
_settingsClone.GlobalSettings().ColorSchemes(),
*this);
// Add an event handler for when the user wants to delete a profile.
_profilesNavState.DeleteProfile({ this, &MainPage::_DeleteProfile });
_colorSchemesNavState = winrt::make<ColorSchemesPageNavigationState>(_settingsClone);
}
// Method Description:
@@ -122,8 +110,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
// Repopulate profile-related menu items
_InitializeProfilesList();
// Update the Nav State with the new version of the settings
_colorSchemesNavState.Globals(_settingsClone.GlobalSettings());
_profilesNavState.Schemes(_settingsClone.GlobalSettings().ColorSchemes());
_colorSchemesNavState.Settings(_settingsClone);
// We'll update the profile in the _profilesNavState whenever we actually navigate to one
// now that the menuItems are repopulated,
@@ -154,7 +141,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
// found the one that was selected before the refresh
SettingsNav().SelectedItem(item);
_Navigate(*selectedItemProfileTag);
_Navigate(*profileTag);
co_return;
}
}
@@ -269,11 +256,12 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
auto profileVM{ _viewModelForProfile(_settingsClone.ProfileDefaults()) };
profileVM.IsBaseLayer(true);
_lastProfilesNavState = winrt::make<ProfilePageNavigationState>(profileVM,
_settingsClone.GlobalSettings().ColorSchemes(),
_lastProfilesNavState,
*this);
// Update the profiles navigation state
_profilesNavState.Profile(profileVM);
contentFrame().Navigate(xaml_typename<Editor::Profiles>(), _profilesNavState);
contentFrame().Navigate(xaml_typename<Editor::Profiles>(), _lastProfilesNavState);
}
else if (clickedItemTag == colorSchemesTag)
{
@@ -287,10 +275,15 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
void MainPage::_Navigate(const Editor::ProfileViewModel& profile)
{
// Update the profiles navigation state
_profilesNavState.Profile(profile);
_lastProfilesNavState = winrt::make<ProfilePageNavigationState>(profile,
_settingsClone.GlobalSettings().ColorSchemes(),
_lastProfilesNavState,
*this);
contentFrame().Navigate(xaml_typename<Editor::Profiles>(), _profilesNavState);
// Add an event handler for when the user wants to delete a profile.
_lastProfilesNavState.DeleteProfile({ this, &MainPage::_DeleteProfile });
contentFrame().Navigate(xaml_typename<Editor::Profiles>(), _lastProfilesNavState);
}
void MainPage::OpenJsonTapped(IInspectable const& /*sender*/, Windows::UI::Xaml::Input::TappedRoutedEventArgs const& /*args*/)
@@ -373,6 +366,25 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
icon.IconSource(iconSource);
profileNavItem.Icon(icon);
// Update the menu item when the icon/name changes
auto weakMenuItem{ make_weak(profileNavItem) };
profile.PropertyChanged([weakMenuItem](const auto&, const WUX::Data::PropertyChangedEventArgs& args) {
if (auto menuItem{ weakMenuItem.get() })
{
const auto& tag{ menuItem.Tag().as<Editor::ProfileViewModel>() };
if (args.PropertyName() == L"Icon")
{
const auto iconSource{ IconPathConverter::IconSourceWUX(tag.Icon()) };
WUX::Controls::IconSourceElement icon;
icon.IconSource(iconSource);
menuItem.Icon(icon);
}
else if (args.PropertyName() == L"Name")
{
menuItem.Content(box_value(tag.Name()));
}
}
});
return profileNavItem;
}

View File

@@ -42,7 +42,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
void _Navigate(const Editor::ProfileViewModel& profile);
ColorSchemesPageNavigationState _colorSchemesNavState{ nullptr };
ProfilePageNavigationState _profilesNavState{ nullptr };
ProfilePageNavigationState _lastProfilesNavState{ nullptr };
};
}

View File

@@ -37,14 +37,6 @@ the MIT License. See LICENSE in the project root for license information. -->
ItemInvoked="SettingsNav_ItemInvoked"
IsBackButtonVisible="Collapsed">
<muxc:NavigationView.HeaderTemplate>
<DataTemplate x:DataType="x:String">
<TextBlock Text="{x:Bind}"
Margin="8,10,0,0"
Style="{StaticResource TitleTextBlockStyle}"/>
</DataTemplate>
</muxc:NavigationView.HeaderTemplate>
<muxc:NavigationView.MenuItems>
<muxc:NavigationViewItem x:Uid="Nav_Launch"
@@ -120,18 +112,15 @@ the MIT License. See LICENSE in the project root for license information. -->
<TextBlock x:Uid="Settings_UnsavedSettingsWarning"
Visibility="Collapsed"
Foreground="Goldenrod"
FontSize="15"
VerticalAlignment="Center"
HorizontalAlignment="Left"
TextAlignment="Left"
Margin="30,0,0,0"/>
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Right" Orientation="Horizontal" Margin="0,0,30,0">
<Button x:Uid="Settings_ResetSettingsButton"
FontSize="15"
ToolTipService.Placement="Mouse"
Click="ResetButton_Click"/>
<Button x:Uid="Settings_SaveSettingsButton"
FontSize="15"
Style="{StaticResource AccentButtonStyle}"
Margin="10,0,0,0"
Click="SaveButton_Click"/>

View File

@@ -33,16 +33,6 @@
</PropertyGroup>
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
<ItemDefinitionGroup>
<ClCompile>
<!-- For CLI11: It uses dynamic_cast to cast types around, which depends
on being compiled with RTTI (/GR). We need this in this project, because
we're including the CLI11 header via the CommandlineArgs project. -->
<RuntimeTypeInfo>true</RuntimeTypeInfo>
</ClCompile>
</ItemDefinitionGroup>
<!-- ========================= Headers ======================== -->
<ItemGroup>
<ClInclude Include="ColorToBrushConverter.h">
@@ -63,6 +53,9 @@
<ClInclude Include="StringIsEmptyConverter.h">
<DependentUpon>Converters.idl</DependentUpon>
</ClInclude>
<ClInclude Include="PaddingConverter.h">
<DependentUpon>Converters.idl</DependentUpon>
</ClInclude>
<ClInclude Include="StringIsNotDesktopConverter.h">
<DependentUpon>Converters.idl</DependentUpon>
</ClInclude>
@@ -145,6 +138,9 @@
<ClCompile Include="StringIsEmptyConverter.cpp">
<DependentUpon>Converters.idl</DependentUpon>
</ClCompile>
<ClCompile Include="PaddingConverter.cpp">
<DependentUpon>Converters.idl</DependentUpon>
</ClCompile>
<ClCompile Include="StringIsNotDesktopConverter.cpp">
<DependentUpon>Converters.idl</DependentUpon>
</ClCompile>
@@ -217,10 +213,6 @@
<PRIResource Include="Resources\en-US\Resources.resw">
<SubType>Designer</SubType>
</PRIResource>
<!-- Make sure to include the CommandlineArgs resources here, so they show up in our scope -->
<PRIResource Include="$(OpenConsoleDir)src\cascadia\CommandlineArgs\Resources\en-US\Resources.resw">
<SubType>Designer</SubType>
</PRIResource>
<OCResourceDirectory Include="Resources" />
<None Include="TerminalSettingsEditor.def" />
<None Include="packages.config" />
@@ -256,15 +248,6 @@
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalSettingsModel\dll\Microsoft.Terminal.Settings.Model.vcxproj">
<Private>false</Private>
</ProjectReference>
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\CommandlineArgs\CommandlineArgs.vcxproj" >
<Private>true</Private>
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
<!-- Make sure to set ReferenceOutputAssembly=false, or we'll try and
MDMERGE with MUX from the CommandlineArgs output, and get duplicate type
errors everywhere. -->
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>
<ItemGroup>

View File

@@ -0,0 +1,65 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "PaddingConverter.h"
#include "PaddingConverter.g.cpp"
using namespace winrt::Windows;
using namespace winrt::Windows::UI::Xaml;
using namespace winrt::Windows::UI::Text;
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
Foundation::IInspectable PaddingConverter::Convert(Foundation::IInspectable const& value,
Windows::UI::Xaml::Interop::TypeName const& /* targetType */,
Foundation::IInspectable const& /* parameter */,
hstring const& /* language */)
{
const auto& padding = winrt::unbox_value<hstring>(value);
const wchar_t singleCharDelim = L',';
std::wstringstream tokenStream(padding.c_str());
std::wstring token;
double maxVal = 0;
size_t* idx = nullptr;
// Get padding values till we run out of delimiter separated values in the stream
// Non-numeral values detected will default to 0
// std::getline will not throw exception unless flags are set on the wstringstream
// std::stod will throw invalid_argument exception if the input is an invalid double value
// std::stod will throw out_of_range exception if the input value is more than DBL_MAX
try
{
while (std::getline(tokenStream, token, singleCharDelim))
{
// std::stod internally calls wcstod which handles whitespace prefix (which is ignored)
// & stops the scan when first char outside the range of radix is encountered
// We'll be permissive till the extent that stod function allows us to be by default
// Ex. a value like 100.3#535w2 will be read as 100.3, but ;df25 will fail
const auto curVal = std::stod(token, idx);
if (curVal > maxVal)
{
maxVal = curVal;
}
}
}
catch (...)
{
// If something goes wrong, even if due to a single bad padding value, we'll return default 0 padding
maxVal = 0;
LOG_CAUGHT_EXCEPTION();
}
return winrt::box_value<double>(maxVal);
}
Foundation::IInspectable PaddingConverter::ConvertBack(Foundation::IInspectable const& value,
Windows::UI::Xaml::Interop::TypeName const& /* targetType */,
Foundation::IInspectable const& /*parameter*/,
hstring const& /* language */)
{
const auto padding{ winrt::unbox_value<double>(value) };
return winrt::box_value(winrt::to_hstring(padding));
}
}

View File

@@ -0,0 +1,9 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
#include "PaddingConverter.g.h"
#include "../inc/cppwinrt_utils.h"
DECLARE_CONVERTER(winrt::Microsoft::Terminal::Settings::Editor, PaddingConverter);

View File

@@ -37,6 +37,8 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
// into the path TextBox, we properly update the checkbox and stored
// _lastBgImagePath. Without this, then we'll permanently hide the text
// box, prevent it from ever being changed again.
//
// We do the same for the starting directory path
PropertyChanged([this](auto&&, const Data::PropertyChangedEventArgs& args) {
if (args.PropertyName() == L"BackgroundImagePath")
{
@@ -46,6 +48,11 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
_NotifyChanges(L"BackgroundImageSettingsVisible");
}
else if (args.PropertyName() == L"StartingDirectory")
{
_NotifyChanges(L"UseParentProcessDirectory");
_NotifyChanges(L"UseCustomStartingDirectory");
}
});
// Cache the original BG image path. If the user clicks "Use desktop
@@ -55,6 +62,12 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
_lastBgImagePath = BackgroundImagePath();
}
// Do the same for the starting directory
if (!StartingDirectory().empty())
{
_lastStartingDirectoryPath = StartingDirectory();
}
}
bool ProfileViewModel::CanDeleteProfile() const
@@ -109,6 +122,52 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
}
}
bool ProfileViewModel::UseParentProcessDirectory()
{
return StartingDirectory().empty();
}
// This function simply returns the opposite of UseParentProcessDirectory.
// We bind the 'IsEnabled' parameters of the textbox and browse button
// to this because it needs to be the reverse of UseParentProcessDirectory
// but we don't want to create a whole new converter for inverting a boolean
bool ProfileViewModel::UseCustomStartingDirectory()
{
return !UseParentProcessDirectory();
}
void ProfileViewModel::UseParentProcessDirectory(const bool useParent)
{
if (useParent)
{
// Stash the current value of StartingDirectory. If the user
// checks and un-checks the "Use parent process directory" button, we want
// the path that we display in the text box to remain unchanged.
//
// Only stash this value if it's not empty
if (!StartingDirectory().empty())
{
_lastStartingDirectoryPath = StartingDirectory();
}
StartingDirectory(L"");
}
else
{
// Restore the path we had previously cached as long as it wasn't empty
// If it was empty, set the starting directory to %USERPROFILE%
// (we need to set it to something non-empty otherwise we will automatically
// disable the text box)
if (_lastStartingDirectoryPath.empty())
{
StartingDirectory(L"%USERPROFILE%");
}
else
{
StartingDirectory(_lastStartingDirectoryPath);
}
}
}
bool ProfileViewModel::BackgroundImageSettingsVisible()
{
return IsBaseLayer() || BackgroundImagePath() != L"";
@@ -147,6 +206,9 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
_BIAlignmentButtons.at(6) = BIAlign_BottomLeft();
_BIAlignmentButtons.at(7) = BIAlign_Bottom();
_BIAlignmentButtons.at(8) = BIAlign_BottomRight();
Profile_Padding().Text(RS_(L"Profile_Padding/Header"));
ToolTipService::SetToolTip(Padding_Presenter(), box_value(RS_(L"Profile_Padding/[using:Windows.UI.Xaml.Controls]ToolTipService/ToolTip")));
}
void Profiles::OnNavigatedTo(const NavigationEventArgs& e)
@@ -216,23 +278,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
state->DeleteProfile();
}
void Profiles::UseParentProcessDirectory_Check(IInspectable const& /*sender*/, RoutedEventArgs const& /*e*/)
{
auto state{ winrt::get_self<ProfilePageNavigationState>(_State) };
state->Profile().StartingDirectory(L"");
// Disable the text box and browse button
StartingDirectory().IsEnabled(false);
StartingDirectoryBrowse().IsEnabled(false);
}
void Profiles::UseParentProcessDirectory_Uncheck(IInspectable const& /*sender*/, RoutedEventArgs const& /*e*/)
{
// Enable the text box and browse button
StartingDirectory().IsEnabled(true);
StartingDirectoryBrowse().IsEnabled(true);
}
fire_and_forget Profiles::BackgroundImage_Click(IInspectable const&, RoutedEventArgs const&)
{
auto lifetime = get_strong();

View File

@@ -21,6 +21,9 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
bool UseDesktopBGImage();
void UseDesktopBGImage(const bool useDesktop);
bool UseParentProcessDirectory();
void UseParentProcessDirectory(const bool useParent);
bool UseCustomStartingDirectory();
bool BackgroundImageSettingsVisible();
GETSET_PROPERTY(bool, IsBaseLayer, false);
@@ -67,6 +70,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
private:
Model::Profile _profile;
winrt::hstring _lastBgImagePath;
winrt::hstring _lastStartingDirectoryPath;
};
struct DeleteProfileEventArgs :
@@ -87,11 +91,23 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
public:
ProfilePageNavigationState(const Editor::ProfileViewModel& viewModel,
const Windows::Foundation::Collections::IMapView<hstring, Model::ColorScheme>& schemes,
const Editor::ProfilePageNavigationState& lastState,
const IHostedInWindow& windowRoot) :
_Profile{ viewModel },
_Schemes{ schemes },
_WindowRoot{ windowRoot }
{
// If there was a previous nav state, and it was for the same
// profile, then copy the selected pivot from it.
if (lastState)
{
const auto& oldGuid = lastState.Profile().Guid();
const auto& newGuid = _Profile.Guid();
if (oldGuid == newGuid)
{
_LastActivePivot = lastState.LastActivePivot();
}
}
}
void DeleteProfile();
@@ -102,26 +118,9 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
TYPED_EVENT(DeleteProfile, Editor::ProfilePageNavigationState, Editor::DeleteProfileEventArgs);
GETSET_PROPERTY(IHostedInWindow, WindowRoot, nullptr);
GETSET_PROPERTY(Editor::ProfilesPivots, LastActivePivot, Editor::ProfilesPivots::General);
public:
// Manually define Profile(), so we can overload the setter
Editor::ProfileViewModel Profile() const noexcept { return _Profile; }
void Profile(const Editor::ProfileViewModel& value) noexcept
{
// If the profile has a different guid than the new one, then reset
// the selected pivot to the "General" tab.
const auto& oldGuid = _Profile.Guid();
const auto& newGuid = value.Guid();
if (oldGuid != newGuid)
{
_LastActivePivot = Editor::ProfilesPivots::General;
}
_Profile = value;
}
GETSET_PROPERTY(Editor::ProfileViewModel, Profile, nullptr);
private:
Editor::ProfileViewModel _Profile{ nullptr };
Windows::Foundation::Collections::IMapView<hstring, Model::ColorScheme> _Schemes;
};

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