Merge remote-tracking branch 'origin/main' into dev/migrie/oop/ragnarok
This commit is contained in:
commit
1413d0145a
2
.gitattributes
vendored
2
.gitattributes
vendored
|
@ -3,6 +3,8 @@
|
||||||
###############################################################################
|
###############################################################################
|
||||||
* -text
|
* -text
|
||||||
|
|
||||||
|
*.inc linguist-language=cpp
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Set default behavior for command prompt diff.
|
# Set default behavior for command prompt diff.
|
||||||
#
|
#
|
||||||
|
|
1
.github/actions/spelling/allow/apis.txt
vendored
1
.github/actions/spelling/allow/apis.txt
vendored
|
@ -25,6 +25,7 @@ DERR
|
||||||
dlldata
|
dlldata
|
||||||
DONTADDTORECENT
|
DONTADDTORECENT
|
||||||
DWORDLONG
|
DWORDLONG
|
||||||
|
enumset
|
||||||
environstrings
|
environstrings
|
||||||
EXPCMDFLAGS
|
EXPCMDFLAGS
|
||||||
EXPCMDSTATE
|
EXPCMDSTATE
|
||||||
|
|
8
.github/actions/spelling/allow/math.txt
vendored
8
.github/actions/spelling/allow/math.txt
vendored
|
@ -1,3 +1,11 @@
|
||||||
|
atan
|
||||||
|
CPrime
|
||||||
|
HBar
|
||||||
|
HPrime
|
||||||
isnan
|
isnan
|
||||||
|
LPrime
|
||||||
|
LStep
|
||||||
powf
|
powf
|
||||||
|
RSub
|
||||||
sqrtf
|
sqrtf
|
||||||
|
ULP
|
||||||
|
|
5
.github/actions/spelling/allow/microsoft.txt
vendored
5
.github/actions/spelling/allow/microsoft.txt
vendored
|
@ -1,5 +1,6 @@
|
||||||
ACLs
|
ACLs
|
||||||
ADMINS
|
ADMINS
|
||||||
|
advapi
|
||||||
altform
|
altform
|
||||||
altforms
|
altforms
|
||||||
appendwttlogging
|
appendwttlogging
|
||||||
|
@ -15,6 +16,7 @@ CPLs
|
||||||
cpptools
|
cpptools
|
||||||
cppvsdbg
|
cppvsdbg
|
||||||
CPRs
|
CPRs
|
||||||
|
cryptbase
|
||||||
DACL
|
DACL
|
||||||
DACLs
|
DACLs
|
||||||
diffs
|
diffs
|
||||||
|
@ -24,7 +26,9 @@ DTDs
|
||||||
DWINRT
|
DWINRT
|
||||||
enablewttlogging
|
enablewttlogging
|
||||||
Intelli
|
Intelli
|
||||||
|
IVisual
|
||||||
LKG
|
LKG
|
||||||
|
LOCKFILE
|
||||||
Lxss
|
Lxss
|
||||||
mfcribbon
|
mfcribbon
|
||||||
microsoft
|
microsoft
|
||||||
|
@ -44,6 +48,7 @@ powershell
|
||||||
propkey
|
propkey
|
||||||
pscustomobject
|
pscustomobject
|
||||||
QWORD
|
QWORD
|
||||||
|
regedit
|
||||||
robocopy
|
robocopy
|
||||||
SACLs
|
SACLs
|
||||||
sdkddkver
|
sdkddkver
|
||||||
|
|
11
.github/actions/spelling/expect/expect.txt
vendored
11
.github/actions/spelling/expect/expect.txt
vendored
|
@ -189,13 +189,12 @@ cacafire
|
||||||
callee
|
callee
|
||||||
capslock
|
capslock
|
||||||
CARETBLINKINGENABLED
|
CARETBLINKINGENABLED
|
||||||
|
carlos
|
||||||
CARRIAGERETURN
|
CARRIAGERETURN
|
||||||
cascadia
|
cascadia
|
||||||
cassert
|
cassert
|
||||||
castsi
|
castsi
|
||||||
catid
|
catid
|
||||||
carlos
|
|
||||||
zamora
|
|
||||||
cazamor
|
cazamor
|
||||||
CBash
|
CBash
|
||||||
cbegin
|
cbegin
|
||||||
|
@ -669,6 +668,7 @@ dwriteglyphrundescriptionclustermap
|
||||||
dxgi
|
dxgi
|
||||||
dxgidwm
|
dxgidwm
|
||||||
dxinterop
|
dxinterop
|
||||||
|
dxsm
|
||||||
dxttbmp
|
dxttbmp
|
||||||
eachother
|
eachother
|
||||||
eae
|
eae
|
||||||
|
@ -1232,6 +1232,7 @@ KLF
|
||||||
KLMNO
|
KLMNO
|
||||||
KLMNOPQRST
|
KLMNOPQRST
|
||||||
KLMNOPQRSTQQQQQ
|
KLMNOPQRSTQQQQQ
|
||||||
|
KPRIORITY
|
||||||
KVM
|
KVM
|
||||||
langid
|
langid
|
||||||
LANGUAGELIST
|
LANGUAGELIST
|
||||||
|
@ -1642,6 +1643,7 @@ onecoreuapuuid
|
||||||
onecoreuuid
|
onecoreuuid
|
||||||
ONECOREWINDOWS
|
ONECOREWINDOWS
|
||||||
onehalf
|
onehalf
|
||||||
|
oneseq
|
||||||
ONLCR
|
ONLCR
|
||||||
openbash
|
openbash
|
||||||
opencode
|
opencode
|
||||||
|
@ -1708,6 +1710,7 @@ pcch
|
||||||
PCCHAR
|
PCCHAR
|
||||||
PCCONSOLE
|
PCCONSOLE
|
||||||
PCD
|
PCD
|
||||||
|
pcg
|
||||||
pch
|
pch
|
||||||
PCHAR
|
PCHAR
|
||||||
PCIDLIST
|
PCIDLIST
|
||||||
|
@ -1803,6 +1806,7 @@ POSX
|
||||||
POSXSCROLL
|
POSXSCROLL
|
||||||
POSYSCROLL
|
POSYSCROLL
|
||||||
ppci
|
ppci
|
||||||
|
PPEB
|
||||||
ppf
|
ppf
|
||||||
ppguid
|
ppguid
|
||||||
ppidl
|
ppidl
|
||||||
|
@ -2022,6 +2026,7 @@ Rike
|
||||||
RIPMSG
|
RIPMSG
|
||||||
RIS
|
RIS
|
||||||
RMENU
|
RMENU
|
||||||
|
rng
|
||||||
roadmap
|
roadmap
|
||||||
robomac
|
robomac
|
||||||
roundtrip
|
roundtrip
|
||||||
|
@ -2724,6 +2729,7 @@ wixproj
|
||||||
wline
|
wline
|
||||||
wlinestream
|
wlinestream
|
||||||
wmain
|
wmain
|
||||||
|
wmemory
|
||||||
WMSZ
|
WMSZ
|
||||||
wnd
|
wnd
|
||||||
WNDALLOC
|
WNDALLOC
|
||||||
|
@ -2850,6 +2856,7 @@ YSize
|
||||||
YSubstantial
|
YSubstantial
|
||||||
YVIRTUALSCREEN
|
YVIRTUALSCREEN
|
||||||
YWalk
|
YWalk
|
||||||
|
zamora
|
||||||
ZCmd
|
ZCmd
|
||||||
ZCtrl
|
ZCtrl
|
||||||
zsh
|
zsh
|
||||||
|
|
2
.github/actions/spelling/expect/web.txt
vendored
2
.github/actions/spelling/expect/web.txt
vendored
|
@ -1,5 +1,7 @@
|
||||||
http
|
http
|
||||||
www
|
www
|
||||||
|
easyrgb
|
||||||
|
php
|
||||||
ecma
|
ecma
|
||||||
rapidtables
|
rapidtables
|
||||||
WCAG
|
WCAG
|
||||||
|
|
|
@ -24,3 +24,4 @@ VERIFY_ARE_EQUAL\(L"[^"]+"
|
||||||
std::memory_order_[\w]+
|
std::memory_order_[\w]+
|
||||||
D2DERR_SHADER_COMPILE_FAILED
|
D2DERR_SHADER_COMPILE_FAILED
|
||||||
TIL_FEATURE_[0-9A-Z_]+
|
TIL_FEATURE_[0-9A-Z_]+
|
||||||
|
vcvars\w*
|
||||||
|
|
67
NOTICE.md
67
NOTICE.md
|
@ -117,7 +117,6 @@ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## dynamic_bitset
|
## dynamic_bitset
|
||||||
|
@ -148,7 +147,6 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## \{fmt\}
|
## \{fmt\}
|
||||||
|
@ -215,7 +213,6 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
@ -249,7 +246,71 @@ SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
DEALINGS IN THE SOFTWARE.
|
DEALINGS IN THE SOFTWARE.
|
||||||
|
```
|
||||||
|
|
||||||
|
## PCG Random Number Generation
|
||||||
|
|
||||||
|
**Source**: [https://github.com/imneme/pcg-cpp](https://github.com/imneme/pcg-cpp)
|
||||||
|
|
||||||
|
### License
|
||||||
|
|
||||||
|
```
|
||||||
|
Copyright (c) 2014-2017 Melissa O'Neill and PCG Project contributors
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
```
|
||||||
|
|
||||||
|
## ConEmu
|
||||||
|
**Source**: [https://github.com/Maximus5/ConEmu](https://github.com/Maximus5/ConEmu)
|
||||||
|
|
||||||
|
### License
|
||||||
|
|
||||||
|
```
|
||||||
|
BSD 3-Clause License
|
||||||
|
|
||||||
|
Copyright (c) 2009-2017, Maximus5 <ConEmu.Maximus5@gmail.com>
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of the copyright holder nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
```
|
```
|
||||||
|
|
||||||
# Microsoft Open Source
|
# Microsoft Open Source
|
||||||
|
|
|
@ -15,7 +15,7 @@ Import-Module .\tools\OpenConsole.psm1
|
||||||
Set-MsBuildDevEnvironment
|
Set-MsBuildDevEnvironment
|
||||||
Get-Format
|
Get-Format
|
||||||
```
|
```
|
||||||
After, go to Tools > Options > Text Editor > C++ > Formatting and checking "Use custom clang-format.exe file" in Visual Studio and choose the clang-format.exe in the repository at /packages/clang-format.win-x86.10.0.0/tools/clang-format.exe by clicking "browse" right under the check box.
|
After, go to Tools > Options > Text Editor > C++ > Formatting and check "Use custom clang-format.exe file" in Visual Studio and choose the clang-format.exe in the repository at /packages/clang-format.win-x86.10.0.0/tools/clang-format.exe by clicking "browse" right under the check box.
|
||||||
|
|
||||||
### Building in PowerShell
|
### Building in PowerShell
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
201
oss/pcg/LICENSE-APACHE.txt
Normal file
201
oss/pcg/LICENSE-APACHE.txt
Normal file
|
@ -0,0 +1,201 @@
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright {yyyy} {name of copyright owner}
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
19
oss/pcg/LICENSE-MIT.txt
Normal file
19
oss/pcg/LICENSE-MIT.txt
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
Copyright (c) 2014-2017 Melissa O'Neill and PCG Project contributors
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
14
oss/pcg/cgmanifest.json
Normal file
14
oss/pcg/cgmanifest.json
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"Registrations": [
|
||||||
|
{
|
||||||
|
"component": {
|
||||||
|
"type": "git",
|
||||||
|
"git": {
|
||||||
|
"repositoryUrl": "https://github.com/imneme/pcg-cpp",
|
||||||
|
"commitHash": "ffd522e7188bef30a00c74dc7eb9de5faff90092"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Version": 1
|
||||||
|
}
|
82
oss/pcg/include/pcg_random.hpp
Normal file
82
oss/pcg/include/pcg_random.hpp
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
// PCG Random Number Generation for C++
|
||||||
|
//
|
||||||
|
// Copyright 2014-2019 Melissa O'Neill <oneill@pcg-random.org>,
|
||||||
|
// and the PCG Project contributors.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (provided in
|
||||||
|
// LICENSE-APACHE.txt and at http://www.apache.org/licenses/LICENSE-2.0)
|
||||||
|
// or under the MIT license (provided in LICENSE-MIT.txt and at
|
||||||
|
// http://opensource.org/licenses/MIT), at your option. This file may not
|
||||||
|
// be copied, modified, or distributed except according to those terms.
|
||||||
|
//
|
||||||
|
// Distributed on an "AS IS" BASIS, WITHOUT WARRANTY OF ANY KIND, either
|
||||||
|
// express or implied. See your chosen license for details.
|
||||||
|
//
|
||||||
|
// For additional information about the PCG random number generation scheme,
|
||||||
|
// visit http://www.pcg-random.org/.
|
||||||
|
//
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Leonard Hecker <lhecker@microsoft.com>:
|
||||||
|
// The following contents are an extract of pcg_engines::oneseq_dxsm_64_32
|
||||||
|
// reduced down to the bare essentials, while retaining base functionality.
|
||||||
|
|
||||||
|
namespace pcg_engines {
|
||||||
|
class oneseq_dxsm_64_32 {
|
||||||
|
using xtype = uint32_t;
|
||||||
|
using itype = uint64_t;
|
||||||
|
|
||||||
|
itype state_;
|
||||||
|
|
||||||
|
static constexpr uint64_t multiplier() {
|
||||||
|
return 6364136223846793005ULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr uint64_t increment() {
|
||||||
|
return 1442695040888963407ULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static itype bump(itype state) {
|
||||||
|
return state * multiplier() + increment();
|
||||||
|
}
|
||||||
|
|
||||||
|
itype base_generate0() {
|
||||||
|
itype old_state = state_;
|
||||||
|
state_ = bump(state_);
|
||||||
|
return old_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit oneseq_dxsm_64_32(itype state = 0xcafef00dd15ea5e5ULL) : state_(bump(state + increment())) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a value in the interval [0, UINT32_MAX].
|
||||||
|
xtype operator()() {
|
||||||
|
constexpr auto xtypebits = uint8_t(sizeof(xtype) * 8);
|
||||||
|
constexpr auto itypebits = uint8_t(sizeof(itype) * 8);
|
||||||
|
|
||||||
|
auto internal = base_generate0();
|
||||||
|
auto hi = xtype(internal >> (itypebits - xtypebits));
|
||||||
|
auto lo = xtype(internal);
|
||||||
|
|
||||||
|
lo |= 1;
|
||||||
|
hi ^= hi >> (xtypebits / 2);
|
||||||
|
hi *= xtype(multiplier());
|
||||||
|
hi ^= hi >> (3 * (xtypebits / 4));
|
||||||
|
hi *= lo;
|
||||||
|
return hi;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a value in the interval [0, upper_bound).
|
||||||
|
xtype operator()(xtype upper_bound) {
|
||||||
|
uint32_t threshold = (UINT64_MAX + uint32_t(1) - upper_bound) % upper_bound;
|
||||||
|
for (;;) {
|
||||||
|
auto r = operator()();
|
||||||
|
if (r >= threshold)
|
||||||
|
return r % upper_bound;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
|
@ -12,6 +12,7 @@
|
||||||
<EventProvider Id="EventProvider_TerminalWin32Host" Name="56c06166-2e2e-5f4d-7ff3-74f4b78c87d6" />
|
<EventProvider Id="EventProvider_TerminalWin32Host" Name="56c06166-2e2e-5f4d-7ff3-74f4b78c87d6" />
|
||||||
<EventProvider Id="EventProvider_TerminalRemoting" Name="d6f04aad-629f-539a-77c1-73f5c3e4aa7b" />
|
<EventProvider Id="EventProvider_TerminalRemoting" Name="d6f04aad-629f-539a-77c1-73f5c3e4aa7b" />
|
||||||
<EventProvider Id="EventProvider_TerminalDirectX" Name="c93e739e-ae50-5a14-78e7-f171e947535d" />
|
<EventProvider Id="EventProvider_TerminalDirectX" Name="c93e739e-ae50-5a14-78e7-f171e947535d" />
|
||||||
|
<EventProvider Id="EventProvider_TerminalUIA" Name="e7ebce59-2161-572d-b263-2f16a6afb9e5"/>
|
||||||
<Profile Id="Terminal.Verbose.File" Name="Terminal" Description="Terminal" LoggingMode="File" DetailLevel="Verbose">
|
<Profile Id="Terminal.Verbose.File" Name="Terminal" Description="Terminal" LoggingMode="File" DetailLevel="Verbose">
|
||||||
<Collectors>
|
<Collectors>
|
||||||
<EventCollectorId Value="EventCollector_Terminal">
|
<EventCollectorId Value="EventCollector_Terminal">
|
||||||
|
@ -23,6 +24,7 @@
|
||||||
<EventProviderId Value="EventProvider_TerminalWin32Host" />
|
<EventProviderId Value="EventProvider_TerminalWin32Host" />
|
||||||
<EventProviderId Value="EventProvider_TerminalRemoting" />
|
<EventProviderId Value="EventProvider_TerminalRemoting" />
|
||||||
<EventProviderId Value="EventProvider_TerminalDirectX" />
|
<EventProviderId Value="EventProvider_TerminalDirectX" />
|
||||||
|
<EventProviderId Value="EventProvider_TerminalUIA" />
|
||||||
</EventProviders>
|
</EventProviders>
|
||||||
</EventCollectorId>
|
</EventCollectorId>
|
||||||
</Collectors>
|
</Collectors>
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
#include "precomp.h"
|
#include "precomp.h"
|
||||||
#include "TextColor.h"
|
#include "TextColor.h"
|
||||||
|
|
||||||
|
#include <til/bit.h>
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
|
|
||||||
// A table mapping 8-bit RGB colors, in the form RRRGGGBB,
|
// A table mapping 8-bit RGB colors, in the form RRRGGGBB,
|
||||||
|
@ -186,7 +188,7 @@ COLORREF TextColor::GetColor(const std::array<COLORREF, 256>& colorTable, const
|
||||||
// the result will be something like 0b00100000.
|
// the result will be something like 0b00100000.
|
||||||
// 5. Use BitScanForward (bsf) to find the index of the most significant 1 bit.
|
// 5. Use BitScanForward (bsf) to find the index of the most significant 1 bit.
|
||||||
const auto haystack = _mm256_loadu_si256(reinterpret_cast<const __m256i*>(colorTable.data())); // 1.
|
const auto haystack = _mm256_loadu_si256(reinterpret_cast<const __m256i*>(colorTable.data())); // 1.
|
||||||
const auto needle = _mm256_set1_epi32(__builtin_bit_cast(int, defaultColor)); // 2.
|
const auto needle = _mm256_set1_epi32(til::bit_cast<int>(defaultColor)); // 2.
|
||||||
const auto result = _mm256_cmpeq_epi32(haystack, needle); // 3.
|
const auto result = _mm256_cmpeq_epi32(haystack, needle); // 3.
|
||||||
const auto mask = _mm256_movemask_ps(_mm256_castsi256_ps(result)); // 4.
|
const auto mask = _mm256_movemask_ps(_mm256_castsi256_ps(result)); // 4.
|
||||||
unsigned long index;
|
unsigned long index;
|
||||||
|
@ -203,7 +205,7 @@ COLORREF TextColor::GetColor(const std::array<COLORREF, 256>& colorTable, const
|
||||||
// --> the index returned by _BitScanForward must be divided by 2.
|
// --> the index returned by _BitScanForward must be divided by 2.
|
||||||
const auto haystack1 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(colorTable.data() + 0));
|
const auto haystack1 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(colorTable.data() + 0));
|
||||||
const auto haystack2 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(colorTable.data() + 4));
|
const auto haystack2 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(colorTable.data() + 4));
|
||||||
const auto needle = _mm_set1_epi32(__builtin_bit_cast(int, defaultColor));
|
const auto needle = _mm_set1_epi32(til::bit_cast<int>(defaultColor));
|
||||||
const auto result1 = _mm_cmpeq_epi32(haystack1, needle);
|
const auto result1 = _mm_cmpeq_epi32(haystack1, needle);
|
||||||
const auto result2 = _mm_cmpeq_epi32(haystack2, needle);
|
const auto result2 = _mm_cmpeq_epi32(haystack2, needle);
|
||||||
const auto result = _mm_packs_epi32(result1, result2); // 3.5
|
const auto result = _mm_packs_epi32(result1, result2); // 3.5
|
||||||
|
|
|
@ -74,7 +74,7 @@
|
||||||
Enabled="false"
|
Enabled="false"
|
||||||
DisplayName="ms-resource:AppName" />
|
DisplayName="ms-resource:AppName" />
|
||||||
</uap5:Extension>
|
</uap5:Extension>
|
||||||
<!-- <uap3:Extension Category="windows.appExtension">
|
<uap3:Extension Category="windows.appExtension">
|
||||||
<uap3:AppExtension Name="com.microsoft.windows.console.host"
|
<uap3:AppExtension Name="com.microsoft.windows.console.host"
|
||||||
Id="OpenConsole"
|
Id="OpenConsole"
|
||||||
DisplayName="OpenConsole"
|
DisplayName="OpenConsole"
|
||||||
|
@ -102,15 +102,15 @@
|
||||||
<com:Interface Id="E686C757-9A35-4A1C-B3CE-0BCC8B5C69F4" ProxyStubClsid="3171DE52-6EFA-4AEF-8A9F-D02BD67E7A4F"/>
|
<com:Interface Id="E686C757-9A35-4A1C-B3CE-0BCC8B5C69F4" ProxyStubClsid="3171DE52-6EFA-4AEF-8A9F-D02BD67E7A4F"/>
|
||||||
<com:Interface Id="59D55CCE-FC8A-48B4-ACE8-0A9286C6557F" ProxyStubClsid="3171DE52-6EFA-4AEF-8A9F-D02BD67E7A4F"/>
|
<com:Interface Id="59D55CCE-FC8A-48B4-ACE8-0A9286C6557F" ProxyStubClsid="3171DE52-6EFA-4AEF-8A9F-D02BD67E7A4F"/>
|
||||||
</com:ComInterface>
|
</com:ComInterface>
|
||||||
</com:Extension> -->
|
</com:Extension>
|
||||||
<com:Extension Category="windows.comServer">
|
<com:Extension Category="windows.comServer">
|
||||||
<com:ComServer>
|
<com:ComServer>
|
||||||
<!-- <com:ExeServer DisplayName="OpenConsole" Executable="OpenConsole.exe">
|
<com:ExeServer DisplayName="OpenConsole" Executable="OpenConsole.exe">
|
||||||
<com:Class Id="2EACA947-7F5F-4CFA-BA87-8F7FBEEFBE69"/>
|
<com:Class Id="2EACA947-7F5F-4CFA-BA87-8F7FBEEFBE69"/>
|
||||||
</com:ExeServer>
|
</com:ExeServer>
|
||||||
<com:ExeServer DisplayName="WindowsTerminal" Executable="WindowsTerminal.exe">
|
<com:ExeServer DisplayName="WindowsTerminal" Executable="WindowsTerminal.exe">
|
||||||
<com:Class Id="E12CFF52-A866-4C77-9A90-F570A7AA2C6B"/>
|
<com:Class Id="E12CFF52-A866-4C77-9A90-F570A7AA2C6B"/>
|
||||||
</com:ExeServer> -->
|
</com:ExeServer>
|
||||||
<com:SurrogateServer DisplayName="WindowsTerminalShellExt">
|
<com:SurrogateServer DisplayName="WindowsTerminalShellExt">
|
||||||
<com:Class Id="9f156763-7844-4dc4-b2b1-901f640f5155" Path="WindowsTerminalShellExt.dll" ThreadingModel="STA"/>
|
<com:Class Id="9f156763-7844-4dc4-b2b1-901f640f5155" Path="WindowsTerminalShellExt.dll" ThreadingModel="STA"/>
|
||||||
</com:SurrogateServer>
|
</com:SurrogateServer>
|
||||||
|
|
|
@ -465,6 +465,10 @@ namespace SettingsModelLocalTests
|
||||||
"name":"action7_startingDirectoryWithTrailingSlash",
|
"name":"action7_startingDirectoryWithTrailingSlash",
|
||||||
"command": { "action": "newWindow", "startingDirectory":"C:\\", "commandline": "bar.exe" }
|
"command": { "action": "newWindow", "startingDirectory":"C:\\", "commandline": "bar.exe" }
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name":"action8_tabTitleEscaping",
|
||||||
|
"command": { "action": "newWindow", "tabTitle":"\\\";foo\\" }
|
||||||
|
}
|
||||||
])" };
|
])" };
|
||||||
|
|
||||||
const auto commands0Json = VerifyParseSucceeded(commands0String);
|
const auto commands0Json = VerifyParseSucceeded(commands0String);
|
||||||
|
@ -473,7 +477,7 @@ namespace SettingsModelLocalTests
|
||||||
VERIFY_ARE_EQUAL(0u, commands.Size());
|
VERIFY_ARE_EQUAL(0u, commands.Size());
|
||||||
auto warnings = implementation::Command::LayerJson(commands, commands0Json);
|
auto warnings = implementation::Command::LayerJson(commands, commands0Json);
|
||||||
VERIFY_ARE_EQUAL(0u, warnings.size());
|
VERIFY_ARE_EQUAL(0u, warnings.size());
|
||||||
VERIFY_ARE_EQUAL(8u, commands.Size());
|
VERIFY_ARE_EQUAL(9u, commands.Size());
|
||||||
|
|
||||||
{
|
{
|
||||||
auto command = commands.Lookup(L"action0");
|
auto command = commands.Lookup(L"action0");
|
||||||
|
@ -586,5 +590,20 @@ namespace SettingsModelLocalTests
|
||||||
L"cmdline: \"%s\"", cmdline.c_str()));
|
L"cmdline: \"%s\"", cmdline.c_str()));
|
||||||
VERIFY_ARE_EQUAL(L"--startingDirectory \"C:\\\\\" -- \"bar.exe\"", terminalArgs.ToCommandline());
|
VERIFY_ARE_EQUAL(L"--startingDirectory \"C:\\\\\" -- \"bar.exe\"", terminalArgs.ToCommandline());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto command = commands.Lookup(L"action8_tabTitleEscaping");
|
||||||
|
VERIFY_IS_NOT_NULL(command);
|
||||||
|
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
||||||
|
VERIFY_ARE_EQUAL(ShortcutAction::NewWindow, command.ActionAndArgs().Action());
|
||||||
|
const auto& realArgs = command.ActionAndArgs().Args().try_as<NewWindowArgs>();
|
||||||
|
VERIFY_IS_NOT_NULL(realArgs);
|
||||||
|
const auto& terminalArgs = realArgs.TerminalArgs();
|
||||||
|
VERIFY_IS_NOT_NULL(terminalArgs);
|
||||||
|
auto cmdline = terminalArgs.ToCommandline();
|
||||||
|
Log::Comment(NoThrowString().Format(
|
||||||
|
L"cmdline: \"%s\"", cmdline.c_str()));
|
||||||
|
VERIFY_ARE_EQUAL(LR"-(--title "\\\"\;foo\\")-", terminalArgs.ToCommandline());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1092,7 +1092,7 @@ namespace SettingsModelLocalTests
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "profile1",
|
"name": "profile1",
|
||||||
"guid": "{6239a42c-1111-49a3-80bd-e8fdd045185c}",
|
"guid": "{6239a42c-2222-49a3-80bd-e8fdd045185c}",
|
||||||
"source": "Terminal.App.UnitTest.1",
|
"source": "Terminal.App.UnitTest.1",
|
||||||
"historySize": 2222
|
"historySize": 2222
|
||||||
},
|
},
|
||||||
|
|
|
@ -272,20 +272,30 @@ namespace SettingsModelLocalTests
|
||||||
void ProfileTests::DuplicateProfileTest()
|
void ProfileTests::DuplicateProfileTest()
|
||||||
{
|
{
|
||||||
static constexpr std::string_view userProfiles{ R"({
|
static constexpr std::string_view userProfiles{ R"({
|
||||||
"profiles": [
|
"profiles": {
|
||||||
{
|
"defaults": {
|
||||||
"name": "profile0",
|
"font": {
|
||||||
"guid": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
|
"size": 123
|
||||||
"backgroundImage": "file:///some/path",
|
}
|
||||||
"hidden": false,
|
},
|
||||||
}
|
"list": [
|
||||||
]
|
{
|
||||||
|
"name": "profile0",
|
||||||
|
"guid": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
|
||||||
|
"backgroundImage": "file:///some/path",
|
||||||
|
"hidden": false,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
})" };
|
})" };
|
||||||
|
|
||||||
const auto settings = winrt::make_self<implementation::CascadiaSettings>(userProfiles);
|
const auto settings = winrt::make_self<implementation::CascadiaSettings>(userProfiles);
|
||||||
const auto profile = settings->AllProfiles().GetAt(0);
|
const auto profile = settings->AllProfiles().GetAt(0);
|
||||||
const auto duplicatedProfile = settings->DuplicateProfile(profile);
|
const auto duplicatedProfile = settings->DuplicateProfile(profile);
|
||||||
|
|
||||||
|
// GH#11392: Ensure duplicated profiles properly inherit the base layer, even for nested objects.
|
||||||
|
VERIFY_ARE_EQUAL(123, duplicatedProfile.FontInfo().FontSize());
|
||||||
|
|
||||||
duplicatedProfile.Guid(profile.Guid());
|
duplicatedProfile.Guid(profile.Guid());
|
||||||
duplicatedProfile.Name(profile.Name());
|
duplicatedProfile.Name(profile.Name());
|
||||||
|
|
||||||
|
@ -300,6 +310,17 @@ namespace SettingsModelLocalTests
|
||||||
// the GUID generated for a dynamic profile (with a source) is different
|
// the GUID generated for a dynamic profile (with a source) is different
|
||||||
// than that of a profile without a source.
|
// than that of a profile without a source.
|
||||||
|
|
||||||
|
static constexpr std::string_view inboxSettings{ R"({
|
||||||
|
"profiles": [
|
||||||
|
{
|
||||||
|
"name" : "profile0",
|
||||||
|
"source": "Terminal.App.UnitTest.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name" : "profile1"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})" };
|
||||||
static constexpr std::string_view userSettings{ R"({
|
static constexpr std::string_view userSettings{ R"({
|
||||||
"profiles": [
|
"profiles": [
|
||||||
{
|
{
|
||||||
|
@ -312,9 +333,9 @@ namespace SettingsModelLocalTests
|
||||||
]
|
]
|
||||||
})" };
|
})" };
|
||||||
|
|
||||||
const auto settings = winrt::make_self<implementation::CascadiaSettings>(userSettings, DefaultJson);
|
const auto settings = winrt::make_self<implementation::CascadiaSettings>(userSettings, inboxSettings);
|
||||||
|
|
||||||
VERIFY_ARE_EQUAL(4u, settings->AllProfiles().Size());
|
VERIFY_ARE_EQUAL(3u, settings->AllProfiles().Size());
|
||||||
|
|
||||||
VERIFY_ARE_EQUAL(L"profile0", settings->AllProfiles().GetAt(0).Name());
|
VERIFY_ARE_EQUAL(L"profile0", settings->AllProfiles().GetAt(0).Name());
|
||||||
VERIFY_IS_TRUE(settings->AllProfiles().GetAt(0).HasGuid());
|
VERIFY_IS_TRUE(settings->AllProfiles().GetAt(0).HasGuid());
|
||||||
|
|
|
@ -53,7 +53,7 @@ namespace SettingsModelLocalTests
|
||||||
// Return Value:
|
// Return Value:
|
||||||
// - the JsonObject representing this instance
|
// - the JsonObject representing this instance
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void RoundtripTest(const std::string& jsonString)
|
void RoundtripTest(const std::string_view& jsonString)
|
||||||
{
|
{
|
||||||
const auto json{ VerifyParseSucceeded(jsonString) };
|
const auto json{ VerifyParseSucceeded(jsonString) };
|
||||||
const auto settings{ T::FromJson(json) };
|
const auto settings{ T::FromJson(json) };
|
||||||
|
@ -69,7 +69,7 @@ namespace SettingsModelLocalTests
|
||||||
|
|
||||||
void SerializationTests::GlobalSettings()
|
void SerializationTests::GlobalSettings()
|
||||||
{
|
{
|
||||||
const std::string globalsString{ R"(
|
static constexpr std::string_view globalsString{ R"(
|
||||||
{
|
{
|
||||||
"defaultProfile": "{61c54bbd-c2c6-5271-96e7-009a87ff44bf}",
|
"defaultProfile": "{61c54bbd-c2c6-5271-96e7-009a87ff44bf}",
|
||||||
|
|
||||||
|
@ -105,7 +105,7 @@ namespace SettingsModelLocalTests
|
||||||
"actions": []
|
"actions": []
|
||||||
})" };
|
})" };
|
||||||
|
|
||||||
const std::string smallGlobalsString{ R"(
|
static constexpr std::string_view smallGlobalsString{ R"(
|
||||||
{
|
{
|
||||||
"defaultProfile": "{61c54bbd-c2c6-5271-96e7-009a87ff44bf}",
|
"defaultProfile": "{61c54bbd-c2c6-5271-96e7-009a87ff44bf}",
|
||||||
"actions": []
|
"actions": []
|
||||||
|
@ -117,7 +117,7 @@ namespace SettingsModelLocalTests
|
||||||
|
|
||||||
void SerializationTests::Profile()
|
void SerializationTests::Profile()
|
||||||
{
|
{
|
||||||
const std::string profileString{ R"(
|
static constexpr std::string_view profileString{ R"(
|
||||||
{
|
{
|
||||||
"name": "Windows PowerShell",
|
"name": "Windows PowerShell",
|
||||||
"guid": "{61c54bbd-c2c6-5271-96e7-009a87ff44bf}",
|
"guid": "{61c54bbd-c2c6-5271-96e7-009a87ff44bf}",
|
||||||
|
@ -152,7 +152,7 @@ namespace SettingsModelLocalTests
|
||||||
"selectionBackground": "#CCAABB",
|
"selectionBackground": "#CCAABB",
|
||||||
|
|
||||||
"useAcrylic": false,
|
"useAcrylic": false,
|
||||||
"acrylicOpacity": 0.5,
|
"opacity": 50,
|
||||||
|
|
||||||
"backgroundImage": "made_you_look.jpeg",
|
"backgroundImage": "made_you_look.jpeg",
|
||||||
"backgroundImageStretchMode": "uniformToFill",
|
"backgroundImageStretchMode": "uniformToFill",
|
||||||
|
@ -167,7 +167,7 @@ namespace SettingsModelLocalTests
|
||||||
"experimental.retroTerminalEffect": false
|
"experimental.retroTerminalEffect": false
|
||||||
})" };
|
})" };
|
||||||
|
|
||||||
const std::string smallProfileString{ R"(
|
static constexpr std::string_view smallProfileString{ R"(
|
||||||
{
|
{
|
||||||
"name": "Custom Profile"
|
"name": "Custom Profile"
|
||||||
})" };
|
})" };
|
||||||
|
@ -175,7 +175,7 @@ namespace SettingsModelLocalTests
|
||||||
// Setting "tabColor" to null tests two things:
|
// Setting "tabColor" to null tests two things:
|
||||||
// - null should count as an explicit user-set value, not falling back to the parent's value
|
// - null should count as an explicit user-set value, not falling back to the parent's value
|
||||||
// - null should be acceptable even though we're working with colors
|
// - null should be acceptable even though we're working with colors
|
||||||
const std::string weirdProfileString{ R"(
|
static constexpr std::string_view weirdProfileString{ R"(
|
||||||
{
|
{
|
||||||
"guid" : "{8b039d4d-77ca-5a83-88e1-dfc8e895a127}",
|
"guid" : "{8b039d4d-77ca-5a83-88e1-dfc8e895a127}",
|
||||||
"name": "Weird Profile",
|
"name": "Weird Profile",
|
||||||
|
@ -192,7 +192,7 @@ namespace SettingsModelLocalTests
|
||||||
|
|
||||||
void SerializationTests::ColorScheme()
|
void SerializationTests::ColorScheme()
|
||||||
{
|
{
|
||||||
const std::string schemeString{ R"({
|
static constexpr std::string_view schemeString{ R"({
|
||||||
"name": "Campbell",
|
"name": "Campbell",
|
||||||
|
|
||||||
"cursorColor": "#FFFFFF",
|
"cursorColor": "#FFFFFF",
|
||||||
|
@ -225,56 +225,56 @@ namespace SettingsModelLocalTests
|
||||||
void SerializationTests::Actions()
|
void SerializationTests::Actions()
|
||||||
{
|
{
|
||||||
// simple command
|
// simple command
|
||||||
const std::string actionsString1{ R"([
|
static constexpr std::string_view actionsString1{ R"([
|
||||||
{ "command": "paste" }
|
{ "command": "paste" }
|
||||||
])" };
|
])" };
|
||||||
|
|
||||||
// complex command
|
// complex command
|
||||||
const std::string actionsString2A{ R"([
|
static constexpr std::string_view actionsString2A{ R"([
|
||||||
{ "command": { "action": "setTabColor" } }
|
{ "command": { "action": "setTabColor" } }
|
||||||
])" };
|
])" };
|
||||||
const std::string actionsString2B{ R"([
|
static constexpr std::string_view actionsString2B{ R"([
|
||||||
{ "command": { "action": "setTabColor", "color": "#112233" } }
|
{ "command": { "action": "setTabColor", "color": "#112233" } }
|
||||||
])" };
|
])" };
|
||||||
const std::string actionsString2C{ R"([
|
static constexpr std::string_view actionsString2C{ R"([
|
||||||
{ "command": { "action": "copy" } },
|
{ "command": { "action": "copy" } },
|
||||||
{ "command": { "action": "copy", "singleLine": true, "copyFormatting": "html" } }
|
{ "command": { "action": "copy", "singleLine": true, "copyFormatting": "html" } }
|
||||||
])" };
|
])" };
|
||||||
|
|
||||||
// simple command with key chords
|
// simple command with key chords
|
||||||
const std::string actionsString3{ R"([
|
static constexpr std::string_view actionsString3{ R"([
|
||||||
{ "command": "toggleAlwaysOnTop", "keys": "ctrl+a" },
|
{ "command": "toggleAlwaysOnTop", "keys": "ctrl+a" },
|
||||||
{ "command": "toggleAlwaysOnTop", "keys": "ctrl+b" }
|
{ "command": "toggleAlwaysOnTop", "keys": "ctrl+b" }
|
||||||
])" };
|
])" };
|
||||||
|
|
||||||
// complex command with key chords
|
// complex command with key chords
|
||||||
const std::string actionsString4A{ R"([
|
static constexpr std::string_view actionsString4A{ R"([
|
||||||
{ "command": { "action": "adjustFontSize", "delta": 1 }, "keys": "ctrl+c" },
|
{ "command": { "action": "adjustFontSize", "delta": 1 }, "keys": "ctrl+c" },
|
||||||
{ "command": { "action": "adjustFontSize", "delta": 1 }, "keys": "ctrl+d" }
|
{ "command": { "action": "adjustFontSize", "delta": 1 }, "keys": "ctrl+d" }
|
||||||
])" };
|
])" };
|
||||||
const std::string actionsString4B{ R"([
|
static constexpr std::string_view actionsString4B{ R"([
|
||||||
{ "command": { "action": "findMatch", "direction": "next" }, "keys": "ctrl+shift+s" },
|
{ "command": { "action": "findMatch", "direction": "next" }, "keys": "ctrl+shift+s" },
|
||||||
{ "command": { "action": "findMatch", "direction": "prev" }, "keys": "ctrl+shift+r" }
|
{ "command": { "action": "findMatch", "direction": "prev" }, "keys": "ctrl+shift+r" }
|
||||||
])" };
|
])" };
|
||||||
|
|
||||||
// command with name and icon and multiple key chords
|
// command with name and icon and multiple key chords
|
||||||
const std::string actionsString5{ R"([
|
static constexpr std::string_view actionsString5{ R"([
|
||||||
{ "icon": "image.png", "name": "Scroll To Top Name", "command": "scrollToTop", "keys": "ctrl+e" },
|
{ "icon": "image.png", "name": "Scroll To Top Name", "command": "scrollToTop", "keys": "ctrl+e" },
|
||||||
{ "command": "scrollToTop", "keys": "ctrl+f" }
|
{ "command": "scrollToTop", "keys": "ctrl+f" }
|
||||||
])" };
|
])" };
|
||||||
|
|
||||||
// complex command with new terminal args
|
// complex command with new terminal args
|
||||||
const std::string actionsString6{ R"([
|
static constexpr std::string_view actionsString6{ R"([
|
||||||
{ "command": { "action": "newTab", "index": 0 }, "keys": "ctrl+g" },
|
{ "command": { "action": "newTab", "index": 0 }, "keys": "ctrl+g" },
|
||||||
])" };
|
])" };
|
||||||
|
|
||||||
// complex command with meaningful null arg
|
// complex command with meaningful null arg
|
||||||
const std::string actionsString7{ R"([
|
static constexpr std::string_view actionsString7{ R"([
|
||||||
{ "command": { "action": "renameWindow", "name": null }, "keys": "ctrl+h" }
|
{ "command": { "action": "renameWindow", "name": null }, "keys": "ctrl+h" }
|
||||||
])" };
|
])" };
|
||||||
|
|
||||||
// nested command
|
// nested command
|
||||||
const std::string actionsString8{ R"([
|
static constexpr std::string_view actionsString8{ R"([
|
||||||
{
|
{
|
||||||
"name": "Change font size...",
|
"name": "Change font size...",
|
||||||
"commands": [
|
"commands": [
|
||||||
|
@ -286,7 +286,7 @@ namespace SettingsModelLocalTests
|
||||||
])" };
|
])" };
|
||||||
|
|
||||||
// iterable command
|
// iterable command
|
||||||
const std::string actionsString9A{ R"([
|
static constexpr std::string_view actionsString9A{ R"([
|
||||||
{
|
{
|
||||||
"name": "New tab",
|
"name": "New tab",
|
||||||
"commands": [
|
"commands": [
|
||||||
|
@ -299,7 +299,7 @@ namespace SettingsModelLocalTests
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
])" };
|
])" };
|
||||||
const std::string actionsString9B{ R"([
|
static constexpr std::string_view actionsString9B{ R"([
|
||||||
{
|
{
|
||||||
"commands":
|
"commands":
|
||||||
[
|
[
|
||||||
|
@ -315,7 +315,7 @@ namespace SettingsModelLocalTests
|
||||||
"name": "Send Input ..."
|
"name": "Send Input ..."
|
||||||
}
|
}
|
||||||
])" };
|
])" };
|
||||||
const std::string actionsString9C{ R""([
|
static constexpr std::string_view actionsString9C{ R""([
|
||||||
{
|
{
|
||||||
"commands":
|
"commands":
|
||||||
[
|
[
|
||||||
|
@ -338,7 +338,7 @@ namespace SettingsModelLocalTests
|
||||||
"name": "Send Input (Evil) ..."
|
"name": "Send Input (Evil) ..."
|
||||||
}
|
}
|
||||||
])"" };
|
])"" };
|
||||||
const std::string actionsString9D{ R""([
|
static constexpr std::string_view actionsString9D{ R""([
|
||||||
{
|
{
|
||||||
"command":
|
"command":
|
||||||
{
|
{
|
||||||
|
@ -352,7 +352,7 @@ namespace SettingsModelLocalTests
|
||||||
])"" };
|
])"" };
|
||||||
|
|
||||||
// unbound command
|
// unbound command
|
||||||
const std::string actionsString10{ R"([
|
static constexpr std::string_view actionsString10{ R"([
|
||||||
{ "command": "unbound", "keys": "ctrl+c" }
|
{ "command": "unbound", "keys": "ctrl+c" }
|
||||||
])" };
|
])" };
|
||||||
|
|
||||||
|
@ -395,7 +395,7 @@ namespace SettingsModelLocalTests
|
||||||
|
|
||||||
void SerializationTests::CascadiaSettings()
|
void SerializationTests::CascadiaSettings()
|
||||||
{
|
{
|
||||||
const std::string settingsString{ R"({
|
static constexpr std::string_view settingsString{ R"({
|
||||||
"$help" : "https://aka.ms/terminal-documentation",
|
"$help" : "https://aka.ms/terminal-documentation",
|
||||||
"$schema" : "https://aka.ms/terminal-profiles-schema",
|
"$schema" : "https://aka.ms/terminal-profiles-schema",
|
||||||
"defaultProfile": "{61c54bbd-1111-5271-96e7-009a87ff44bf}",
|
"defaultProfile": "{61c54bbd-1111-5271-96e7-009a87ff44bf}",
|
||||||
|
@ -465,7 +465,7 @@ namespace SettingsModelLocalTests
|
||||||
|
|
||||||
void SerializationTests::LegacyFontSettings()
|
void SerializationTests::LegacyFontSettings()
|
||||||
{
|
{
|
||||||
const std::string profileString{ R"(
|
static constexpr std::string_view profileString{ R"(
|
||||||
{
|
{
|
||||||
"name": "Profile with legacy font settings",
|
"name": "Profile with legacy font settings",
|
||||||
|
|
||||||
|
@ -474,7 +474,7 @@ namespace SettingsModelLocalTests
|
||||||
"fontWeight": "normal"
|
"fontWeight": "normal"
|
||||||
})" };
|
})" };
|
||||||
|
|
||||||
const std::string expectedOutput{ R"(
|
static constexpr std::string_view expectedOutput{ R"(
|
||||||
{
|
{
|
||||||
"name": "Profile with legacy font settings",
|
"name": "Profile with legacy font settings",
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
|
|
||||||
|
#include <til/rand.h>
|
||||||
|
|
||||||
#include "../TerminalSettingsModel/CascadiaSettings.h"
|
#include "../TerminalSettingsModel/CascadiaSettings.h"
|
||||||
#include "../TerminalSettingsModel/TerminalSettings.h"
|
#include "../TerminalSettingsModel/TerminalSettings.h"
|
||||||
#include "TestUtils.h"
|
#include "TestUtils.h"
|
||||||
|
@ -34,14 +36,12 @@ namespace SettingsModelLocalTests
|
||||||
END_TEST_CLASS()
|
END_TEST_CLASS()
|
||||||
|
|
||||||
TEST_METHOD(TryCreateWinRTType);
|
TEST_METHOD(TryCreateWinRTType);
|
||||||
|
|
||||||
TEST_METHOD(TestTerminalArgsForBinding);
|
TEST_METHOD(TestTerminalArgsForBinding);
|
||||||
|
TEST_METHOD(CommandLineToArgvW);
|
||||||
|
TEST_METHOD(GetProfileForArgsWithCommandline);
|
||||||
TEST_METHOD(MakeSettingsForProfile);
|
TEST_METHOD(MakeSettingsForProfile);
|
||||||
TEST_METHOD(MakeSettingsForDefaultProfileThatDoesntExist);
|
TEST_METHOD(MakeSettingsForDefaultProfileThatDoesntExist);
|
||||||
|
|
||||||
TEST_METHOD(TestLayerProfileOnColorScheme);
|
TEST_METHOD(TestLayerProfileOnColorScheme);
|
||||||
|
|
||||||
TEST_METHOD(TestCommandlineToTitlePromotion);
|
TEST_METHOD(TestCommandlineToTitlePromotion);
|
||||||
|
|
||||||
TEST_CLASS_SETUP(ClassSetup)
|
TEST_CLASS_SETUP(ClassSetup)
|
||||||
|
@ -60,6 +60,139 @@ namespace SettingsModelLocalTests
|
||||||
VERIFY_ARE_NOT_EQUAL(oldFontSize, newFontSize);
|
VERIFY_ARE_NOT_EQUAL(oldFontSize, newFontSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CascadiaSettings::_normalizeCommandLine abuses some aspects from CommandLineToArgvW
|
||||||
|
// to simplify the implementation. It assumes that all arguments returned by
|
||||||
|
// CommandLineToArgvW are returned back to back in memory as "arg1\0arg2\0arg3\0...".
|
||||||
|
// This test ensures CommandLineToArgvW doesn't change just to be sure.
|
||||||
|
void TerminalSettingsTests::CommandLineToArgvW()
|
||||||
|
{
|
||||||
|
pcg_engines::oneseq_dxsm_64_32 rng{ til::gen_random<uint64_t>() };
|
||||||
|
|
||||||
|
const auto expectedArgc = static_cast<int>(rng(16) + 1);
|
||||||
|
std::wstring expectedArgv;
|
||||||
|
std::wstring input;
|
||||||
|
|
||||||
|
// We generate up to 16 arguments. Each argument is up to 64 chars long, is quoted
|
||||||
|
// (2 chars, only applies to the input) and separated by a whitespace (1 char).
|
||||||
|
expectedArgv.reserve(expectedArgc * 65);
|
||||||
|
input.reserve(expectedArgc * 67);
|
||||||
|
|
||||||
|
for (int i = 0; i < expectedArgc; ++i)
|
||||||
|
{
|
||||||
|
const bool useQuotes = static_cast<bool>(rng(2));
|
||||||
|
const auto count = static_cast<size_t>(rng(64));
|
||||||
|
const auto ch = static_cast<wchar_t>(rng('z' - 'a' + 1) + 'a');
|
||||||
|
|
||||||
|
if (i != 0)
|
||||||
|
{
|
||||||
|
expectedArgv.push_back(L'\0');
|
||||||
|
input.push_back(L' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (useQuotes)
|
||||||
|
{
|
||||||
|
input.push_back(L'"');
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedArgv.append(count, ch);
|
||||||
|
input.append(count, ch);
|
||||||
|
|
||||||
|
if (useQuotes)
|
||||||
|
{
|
||||||
|
input.push_back(L'"');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int argc;
|
||||||
|
wil::unique_hlocal_ptr<PWSTR[]> argv{ ::CommandLineToArgvW(input.c_str(), &argc) };
|
||||||
|
VERIFY_ARE_EQUAL(expectedArgc, argc);
|
||||||
|
VERIFY_IS_NOT_NULL(argv);
|
||||||
|
|
||||||
|
const auto lastArg = argv[argc - 1];
|
||||||
|
const auto beg = argv[0];
|
||||||
|
const auto end = lastArg + wcslen(lastArg);
|
||||||
|
VERIFY_IS_GREATER_THAN(end, beg);
|
||||||
|
VERIFY_ARE_EQUAL(expectedArgv.size(), static_cast<size_t>(end - beg));
|
||||||
|
VERIFY_ARE_EQUAL(0, memcmp(beg, expectedArgv.data(), expectedArgv.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void TerminalSettingsTests::GetProfileForArgsWithCommandline()
|
||||||
|
{
|
||||||
|
// I'm exclusively using cmd.exe as I know exactly where it resides at.
|
||||||
|
static constexpr std::string_view settingsJson{ R"({
|
||||||
|
"profiles": {
|
||||||
|
"defaults": {
|
||||||
|
"historySize": 123
|
||||||
|
},
|
||||||
|
"list": [
|
||||||
|
{
|
||||||
|
"guid": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
|
||||||
|
"commandline": "%SystemRoot%\\System32\\cmd.exe"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"guid": "{6239a42c-1111-49a3-80bd-e8fdd045185c}",
|
||||||
|
"commandline": "cmd.exe /A"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"guid": "{6239a42c-2222-49a3-80bd-e8fdd045185c}",
|
||||||
|
"commandline": "cmd.exe /A /B"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"guid": "{6239a42c-3333-49a3-80bd-e8fdd045185c}",
|
||||||
|
"commandline": "cmd.exe /A /C",
|
||||||
|
"connectionType": "{9a9977a7-1fe0-49c0-b6c0-13a0cd1c98a1}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
})" };
|
||||||
|
|
||||||
|
const auto settings = winrt::make_self<implementation::CascadiaSettings>(settingsJson);
|
||||||
|
|
||||||
|
struct TestCase
|
||||||
|
{
|
||||||
|
std::wstring_view input;
|
||||||
|
int expected;
|
||||||
|
};
|
||||||
|
|
||||||
|
static constexpr std::array testCases{
|
||||||
|
// Base test.
|
||||||
|
TestCase{ L"cmd.exe", 0 },
|
||||||
|
// SearchPathW() normalization + case insensitive matching.
|
||||||
|
TestCase{ L"cmd.exe /a", 1 },
|
||||||
|
TestCase{ L"C:\\Windows\\System32\\cmd.exe /A", 1 },
|
||||||
|
// Test that we don't pick the equally long but different "/A /B" variant.
|
||||||
|
TestCase{ L"C:\\Windows\\System32\\cmd.exe /A /C", 1 },
|
||||||
|
// Test that we don't pick the shorter "/A" variant,
|
||||||
|
// but do pick the shorter "/A /B" variant for longer inputs.
|
||||||
|
TestCase{ L"cmd.exe /A /B", 2 },
|
||||||
|
TestCase{ L"cmd.exe /A /B /C", 2 },
|
||||||
|
// Ignore profiles with a connection type, like the Azure cloud shell.
|
||||||
|
// Instead it should pick any other prefix.
|
||||||
|
TestCase{ L"C:\\Windows\\System32\\cmd.exe /A /C", 1 },
|
||||||
|
// Return base layer profile for missing profiles.
|
||||||
|
TestCase{ L"C:\\Windows\\regedit.exe", -1 },
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const auto& testCase : testCases)
|
||||||
|
{
|
||||||
|
NewTerminalArgs args;
|
||||||
|
args.Commandline(testCase.input);
|
||||||
|
|
||||||
|
const auto profile = settings->GetProfileForArgs(args);
|
||||||
|
VERIFY_IS_NOT_NULL(profile);
|
||||||
|
|
||||||
|
if (testCase.expected < 0)
|
||||||
|
{
|
||||||
|
VERIFY_ARE_EQUAL(123, profile.HistorySize());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GUID expectedGUID{ 0x6239a42c, static_cast<uint16_t>(0x1111 * testCase.expected), 0x49a3, { 0x80, 0xbd, 0xe8, 0xfd, 0xd0, 0x45, 0x18, 0x5c } };
|
||||||
|
VERIFY_ARE_EQUAL(expectedGUID, static_cast<const GUID&>(profile.Guid()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TerminalSettingsTests::TestTerminalArgsForBinding()
|
void TerminalSettingsTests::TestTerminalArgsForBinding()
|
||||||
{
|
{
|
||||||
static constexpr std::string_view settingsJson{ R"(
|
static constexpr std::string_view settingsJson{ R"(
|
||||||
|
|
|
@ -1031,9 +1031,11 @@ namespace TerminalAppLocalTests
|
||||||
// The first action is going to always be a new-tab action
|
// The first action is going to always be a new-tab action
|
||||||
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, appArgs._startupActions.at(0).Action());
|
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, appArgs._startupActions.at(0).Action());
|
||||||
|
|
||||||
auto actionAndArgs = appArgs._startupActions.at(1);
|
const auto actionAndArgs = appArgs._startupActions.at(1);
|
||||||
VERIFY_ARE_EQUAL(ShortcutAction::NextTab, actionAndArgs.Action());
|
VERIFY_ARE_EQUAL(ShortcutAction::NextTab, actionAndArgs.Action());
|
||||||
VERIFY_IS_NULL(actionAndArgs.Args());
|
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
|
||||||
|
const auto myArgs = actionAndArgs.Args().as<NextTabArgs>();
|
||||||
|
VERIFY_ARE_EQUAL(TabSwitcherMode::Disabled, myArgs.SwitcherMode().Value());
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
AppCommandlineArgs appArgs{};
|
AppCommandlineArgs appArgs{};
|
||||||
|
@ -1047,7 +1049,9 @@ namespace TerminalAppLocalTests
|
||||||
|
|
||||||
auto actionAndArgs = appArgs._startupActions.at(1);
|
auto actionAndArgs = appArgs._startupActions.at(1);
|
||||||
VERIFY_ARE_EQUAL(ShortcutAction::PrevTab, actionAndArgs.Action());
|
VERIFY_ARE_EQUAL(ShortcutAction::PrevTab, actionAndArgs.Action());
|
||||||
VERIFY_IS_NULL(actionAndArgs.Args());
|
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
|
||||||
|
const auto myArgs = actionAndArgs.Args().as<PrevTabArgs>();
|
||||||
|
VERIFY_ARE_EQUAL(TabSwitcherMode::Disabled, myArgs.SwitcherMode().Value());
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
AppCommandlineArgs appArgs{};
|
AppCommandlineArgs appArgs{};
|
||||||
|
|
|
@ -16,6 +16,31 @@ using namespace winrt::Microsoft::Terminal::Control;
|
||||||
|
|
||||||
namespace TerminalAppLocalTests
|
namespace TerminalAppLocalTests
|
||||||
{
|
{
|
||||||
|
static constexpr std::wstring_view inboxSettings{ LR"({
|
||||||
|
"schemes": [{
|
||||||
|
"name": "Campbell",
|
||||||
|
"foreground": "#CCCCCC",
|
||||||
|
"background": "#0C0C0C",
|
||||||
|
"cursorColor": "#FFFFFF",
|
||||||
|
"black": "#0C0C0C",
|
||||||
|
"red": "#C50F1F",
|
||||||
|
"green": "#13A10E",
|
||||||
|
"yellow": "#C19C00",
|
||||||
|
"blue": "#0037DA",
|
||||||
|
"purple": "#881798",
|
||||||
|
"cyan": "#3A96DD",
|
||||||
|
"white": "#CCCCCC",
|
||||||
|
"brightBlack": "#767676",
|
||||||
|
"brightRed": "#E74856",
|
||||||
|
"brightGreen": "#16C60C",
|
||||||
|
"brightYellow": "#F9F1A5",
|
||||||
|
"brightBlue": "#3B78FF",
|
||||||
|
"brightPurple": "#B4009E",
|
||||||
|
"brightCyan": "#61D6D6",
|
||||||
|
"brightWhite": "#F2F2F2"
|
||||||
|
}]
|
||||||
|
})" };
|
||||||
|
|
||||||
// TODO:microsoft/terminal#3838:
|
// TODO:microsoft/terminal#3838:
|
||||||
// Unfortunately, these tests _WILL NOT_ work in our CI. We're waiting for
|
// Unfortunately, these tests _WILL NOT_ work in our CI. We're waiting for
|
||||||
// an updated TAEF that will let us install framework packages when the test
|
// an updated TAEF that will let us install framework packages when the test
|
||||||
|
@ -107,11 +132,10 @@ namespace TerminalAppLocalTests
|
||||||
"iterateOn": "profiles",
|
"iterateOn": "profiles",
|
||||||
"command": { "action": "splitPane", "profile": "${profile.name}" }
|
"command": { "action": "splitPane", "profile": "${profile.name}" }
|
||||||
},
|
},
|
||||||
],
|
]
|
||||||
"schemes": [ { "name": "Campbell" } ] // This is included here to prevent settings validation errors.
|
|
||||||
})" };
|
})" };
|
||||||
|
|
||||||
CascadiaSettings settings{ settingsJson, {} };
|
CascadiaSettings settings{ settingsJson, inboxSettings };
|
||||||
|
|
||||||
VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());
|
VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());
|
||||||
|
|
||||||
|
@ -231,11 +255,10 @@ namespace TerminalAppLocalTests
|
||||||
"iterateOn": "profiles",
|
"iterateOn": "profiles",
|
||||||
"command": { "action": "splitPane", "profile": "${profile.name}" }
|
"command": { "action": "splitPane", "profile": "${profile.name}" }
|
||||||
},
|
},
|
||||||
],
|
]
|
||||||
"schemes": [ { "name": "Campbell" } ] // This is included here to prevent settings validation errors.
|
|
||||||
})" };
|
})" };
|
||||||
|
|
||||||
CascadiaSettings settings{ settingsJson, {} };
|
CascadiaSettings settings{ settingsJson, inboxSettings };
|
||||||
|
|
||||||
VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());
|
VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());
|
||||||
|
|
||||||
|
@ -357,11 +380,10 @@ namespace TerminalAppLocalTests
|
||||||
"iterateOn": "profiles",
|
"iterateOn": "profiles",
|
||||||
"command": { "action": "splitPane", "profile": "${profile.name}" }
|
"command": { "action": "splitPane", "profile": "${profile.name}" }
|
||||||
},
|
},
|
||||||
],
|
]
|
||||||
"schemes": [ { "name": "Campbell" } ] // This is included here to prevent settings validation errors.
|
|
||||||
})" };
|
})" };
|
||||||
|
|
||||||
CascadiaSettings settings{ settingsJson, {} };
|
CascadiaSettings settings{ settingsJson, inboxSettings };
|
||||||
|
|
||||||
VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());
|
VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());
|
||||||
|
|
||||||
|
@ -495,11 +517,10 @@ namespace TerminalAppLocalTests
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
],
|
]
|
||||||
"schemes": [ { "name": "Campbell" } ] // This is included here to prevent settings validation errors.
|
|
||||||
})" };
|
})" };
|
||||||
|
|
||||||
CascadiaSettings settings{ settingsJson, {} };
|
CascadiaSettings settings{ settingsJson, inboxSettings };
|
||||||
|
|
||||||
VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());
|
VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());
|
||||||
VERIFY_ARE_EQUAL(3u, settings.ActiveProfiles().Size());
|
VERIFY_ARE_EQUAL(3u, settings.ActiveProfiles().Size());
|
||||||
|
@ -590,11 +611,10 @@ namespace TerminalAppLocalTests
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
],
|
]
|
||||||
"schemes": [ { "name": "Campbell" } ] // This is included here to prevent settings validation errors.
|
|
||||||
})" };
|
})" };
|
||||||
|
|
||||||
CascadiaSettings settings{ settingsJson, {} };
|
CascadiaSettings settings{ settingsJson, inboxSettings };
|
||||||
|
|
||||||
VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());
|
VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());
|
||||||
VERIFY_ARE_EQUAL(3u, settings.ActiveProfiles().Size());
|
VERIFY_ARE_EQUAL(3u, settings.ActiveProfiles().Size());
|
||||||
|
@ -714,11 +734,10 @@ namespace TerminalAppLocalTests
|
||||||
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "down" } }
|
{ "command": { "action": "splitPane", "profile": "${profile.name}", "split": "down" } }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
]
|
||||||
"schemes": [ { "name": "Campbell" } ] // This is included here to prevent settings validation errors.
|
|
||||||
})" };
|
})" };
|
||||||
|
|
||||||
CascadiaSettings settings{ settingsJson, {} };
|
CascadiaSettings settings{ settingsJson, inboxSettings };
|
||||||
|
|
||||||
VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());
|
VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());
|
||||||
VERIFY_ARE_EQUAL(3u, settings.ActiveProfiles().Size());
|
VERIFY_ARE_EQUAL(3u, settings.ActiveProfiles().Size());
|
||||||
|
@ -851,11 +870,10 @@ namespace TerminalAppLocalTests
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
]
|
||||||
"schemes": [ { "name": "Campbell" } ] // This is included here to prevent settings validation errors.
|
|
||||||
})" };
|
})" };
|
||||||
|
|
||||||
CascadiaSettings settings{ settingsJson, {} };
|
CascadiaSettings settings{ settingsJson, inboxSettings };
|
||||||
|
|
||||||
VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());
|
VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());
|
||||||
VERIFY_ARE_EQUAL(3u, settings.ActiveProfiles().Size());
|
VERIFY_ARE_EQUAL(3u, settings.ActiveProfiles().Size());
|
||||||
|
@ -954,11 +972,10 @@ namespace TerminalAppLocalTests
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
]
|
||||||
"schemes": [ { "name": "Campbell" } ] // This is included here to prevent settings validation errors.
|
|
||||||
})" };
|
})" };
|
||||||
|
|
||||||
CascadiaSettings settings{ settingsJson, {} };
|
CascadiaSettings settings{ settingsJson, inboxSettings };
|
||||||
|
|
||||||
VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());
|
VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());
|
||||||
VERIFY_ARE_EQUAL(3u, settings.ActiveProfiles().Size());
|
VERIFY_ARE_EQUAL(3u, settings.ActiveProfiles().Size());
|
||||||
|
@ -1085,9 +1102,72 @@ namespace TerminalAppLocalTests
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"schemes": [
|
"schemes": [
|
||||||
{ "name": "scheme_0" },
|
{
|
||||||
{ "name": "scheme_1" },
|
"name": "Campbell",
|
||||||
{ "name": "scheme_2" },
|
"foreground": "#CCCCCC",
|
||||||
|
"background": "#0C0C0C",
|
||||||
|
"cursorColor": "#FFFFFF",
|
||||||
|
"black": "#0C0C0C",
|
||||||
|
"red": "#C50F1F",
|
||||||
|
"green": "#13A10E",
|
||||||
|
"yellow": "#C19C00",
|
||||||
|
"blue": "#0037DA",
|
||||||
|
"purple": "#881798",
|
||||||
|
"cyan": "#3A96DD",
|
||||||
|
"white": "#CCCCCC",
|
||||||
|
"brightBlack": "#767676",
|
||||||
|
"brightRed": "#E74856",
|
||||||
|
"brightGreen": "#16C60C",
|
||||||
|
"brightYellow": "#F9F1A5",
|
||||||
|
"brightBlue": "#3B78FF",
|
||||||
|
"brightPurple": "#B4009E",
|
||||||
|
"brightCyan": "#61D6D6",
|
||||||
|
"brightWhite": "#F2F2F2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Campbell PowerShell",
|
||||||
|
"foreground": "#CCCCCC",
|
||||||
|
"background": "#012456",
|
||||||
|
"cursorColor": "#FFFFFF",
|
||||||
|
"black": "#0C0C0C",
|
||||||
|
"red": "#C50F1F",
|
||||||
|
"green": "#13A10E",
|
||||||
|
"yellow": "#C19C00",
|
||||||
|
"blue": "#0037DA",
|
||||||
|
"purple": "#881798",
|
||||||
|
"cyan": "#3A96DD",
|
||||||
|
"white": "#CCCCCC",
|
||||||
|
"brightBlack": "#767676",
|
||||||
|
"brightRed": "#E74856",
|
||||||
|
"brightGreen": "#16C60C",
|
||||||
|
"brightYellow": "#F9F1A5",
|
||||||
|
"brightBlue": "#3B78FF",
|
||||||
|
"brightPurple": "#B4009E",
|
||||||
|
"brightCyan": "#61D6D6",
|
||||||
|
"brightWhite": "#F2F2F2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Vintage",
|
||||||
|
"foreground": "#C0C0C0",
|
||||||
|
"background": "#000000",
|
||||||
|
"cursorColor": "#FFFFFF",
|
||||||
|
"black": "#000000",
|
||||||
|
"red": "#800000",
|
||||||
|
"green": "#008000",
|
||||||
|
"yellow": "#808000",
|
||||||
|
"blue": "#000080",
|
||||||
|
"purple": "#800080",
|
||||||
|
"cyan": "#008080",
|
||||||
|
"white": "#C0C0C0",
|
||||||
|
"brightBlack": "#808080",
|
||||||
|
"brightRed": "#FF0000",
|
||||||
|
"brightGreen": "#00FF00",
|
||||||
|
"brightYellow": "#FFFF00",
|
||||||
|
"brightBlue": "#0000FF",
|
||||||
|
"brightPurple": "#FF00FF",
|
||||||
|
"brightCyan": "#00FFFF",
|
||||||
|
"brightWhite": "#FFFFFF"
|
||||||
|
}
|
||||||
],
|
],
|
||||||
"actions": [
|
"actions": [
|
||||||
{
|
{
|
||||||
|
@ -1100,10 +1180,6 @@ namespace TerminalAppLocalTests
|
||||||
|
|
||||||
CascadiaSettings settings{ settingsJson, {} };
|
CascadiaSettings settings{ settingsJson, {} };
|
||||||
|
|
||||||
// Since at least one profile does not reference a color scheme,
|
|
||||||
// we add a warning saying "the color scheme is unknown"
|
|
||||||
VERIFY_ARE_EQUAL(1u, settings.Warnings().Size());
|
|
||||||
|
|
||||||
VERIFY_ARE_EQUAL(3u, settings.ActiveProfiles().Size());
|
VERIFY_ARE_EQUAL(3u, settings.ActiveProfiles().Size());
|
||||||
|
|
||||||
auto nameMap{ settings.ActionMap().NameMap() };
|
auto nameMap{ settings.ActionMap().NameMap() };
|
||||||
|
@ -1130,8 +1206,6 @@ namespace TerminalAppLocalTests
|
||||||
auto expandedCommands = winrt::TerminalApp::implementation::TerminalPage::_ExpandCommands(nameMap, settings.ActiveProfiles().GetView(), settings.GlobalSettings().ColorSchemes());
|
auto expandedCommands = winrt::TerminalApp::implementation::TerminalPage::_ExpandCommands(nameMap, settings.ActiveProfiles().GetView(), settings.GlobalSettings().ColorSchemes());
|
||||||
_logCommandNames(expandedCommands.GetView());
|
_logCommandNames(expandedCommands.GetView());
|
||||||
|
|
||||||
// This is the same warning as above
|
|
||||||
VERIFY_ARE_EQUAL(1u, settings.Warnings().Size());
|
|
||||||
VERIFY_ARE_EQUAL(3u, expandedCommands.Size());
|
VERIFY_ARE_EQUAL(3u, expandedCommands.Size());
|
||||||
|
|
||||||
// Yes, this test is testing splitPane with profiles named after each
|
// Yes, this test is testing splitPane with profiles named after each
|
||||||
|
@ -1139,7 +1213,7 @@ namespace TerminalAppLocalTests
|
||||||
// just easy tests to write.
|
// just easy tests to write.
|
||||||
|
|
||||||
{
|
{
|
||||||
auto command = expandedCommands.Lookup(L"iterable command scheme_0");
|
auto command = expandedCommands.Lookup(L"iterable command Campbell");
|
||||||
VERIFY_IS_NOT_NULL(command);
|
VERIFY_IS_NOT_NULL(command);
|
||||||
auto actionAndArgs = command.ActionAndArgs();
|
auto actionAndArgs = command.ActionAndArgs();
|
||||||
VERIFY_IS_NOT_NULL(actionAndArgs);
|
VERIFY_IS_NOT_NULL(actionAndArgs);
|
||||||
|
@ -1153,11 +1227,11 @@ namespace TerminalAppLocalTests
|
||||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
|
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
|
||||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
|
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
|
||||||
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
|
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
|
||||||
VERIFY_ARE_EQUAL(L"scheme_0", realArgs.TerminalArgs().Profile());
|
VERIFY_ARE_EQUAL(L"Campbell", realArgs.TerminalArgs().Profile());
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
auto command = expandedCommands.Lookup(L"iterable command scheme_1");
|
auto command = expandedCommands.Lookup(L"iterable command Campbell PowerShell");
|
||||||
VERIFY_IS_NOT_NULL(command);
|
VERIFY_IS_NOT_NULL(command);
|
||||||
auto actionAndArgs = command.ActionAndArgs();
|
auto actionAndArgs = command.ActionAndArgs();
|
||||||
VERIFY_IS_NOT_NULL(actionAndArgs);
|
VERIFY_IS_NOT_NULL(actionAndArgs);
|
||||||
|
@ -1171,11 +1245,11 @@ namespace TerminalAppLocalTests
|
||||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
|
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
|
||||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
|
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
|
||||||
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
|
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
|
||||||
VERIFY_ARE_EQUAL(L"scheme_1", realArgs.TerminalArgs().Profile());
|
VERIFY_ARE_EQUAL(L"Campbell PowerShell", realArgs.TerminalArgs().Profile());
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
auto command = expandedCommands.Lookup(L"iterable command scheme_2");
|
auto command = expandedCommands.Lookup(L"iterable command Vintage");
|
||||||
VERIFY_IS_NOT_NULL(command);
|
VERIFY_IS_NOT_NULL(command);
|
||||||
auto actionAndArgs = command.ActionAndArgs();
|
auto actionAndArgs = command.ActionAndArgs();
|
||||||
VERIFY_IS_NOT_NULL(actionAndArgs);
|
VERIFY_IS_NOT_NULL(actionAndArgs);
|
||||||
|
@ -1189,7 +1263,7 @@ namespace TerminalAppLocalTests
|
||||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
|
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
|
||||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
|
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
|
||||||
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
|
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
|
||||||
VERIFY_ARE_EQUAL(L"scheme_2", realArgs.TerminalArgs().Profile());
|
VERIFY_ARE_EQUAL(L"Vintage", realArgs.TerminalArgs().Profile());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -751,7 +751,7 @@ namespace TerminalAppLocalTests
|
||||||
});
|
});
|
||||||
VERIFY_SUCCEEDED(result);
|
VERIFY_SUCCEEDED(result);
|
||||||
|
|
||||||
Log::Comment(L"Move focus. This will cause us to un-zoom.");
|
Log::Comment(L"Move focus. We should still be zoomed.");
|
||||||
result = RunOnUIThread([&page]() {
|
result = RunOnUIThread([&page]() {
|
||||||
// Set up action
|
// Set up action
|
||||||
MoveFocusArgs args{ FocusDirection::Left };
|
MoveFocusArgs args{ FocusDirection::Left };
|
||||||
|
@ -761,7 +761,7 @@ namespace TerminalAppLocalTests
|
||||||
|
|
||||||
auto firstTab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
auto firstTab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||||
VERIFY_ARE_EQUAL(2, firstTab->GetLeafPaneCount());
|
VERIFY_ARE_EQUAL(2, firstTab->GetLeafPaneCount());
|
||||||
VERIFY_IS_FALSE(firstTab->IsZoomed());
|
VERIFY_IS_TRUE(firstTab->IsZoomed());
|
||||||
});
|
});
|
||||||
VERIFY_SUCCEEDED(result);
|
VERIFY_SUCCEEDED(result);
|
||||||
}
|
}
|
||||||
|
@ -1357,7 +1357,8 @@ namespace TerminalAppLocalTests
|
||||||
|
|
||||||
Log::Comment(L"Color should be changed to the preview");
|
Log::Comment(L"Color should be changed to the preview");
|
||||||
VERIFY_ARE_EQUAL(til::color{ 0xff000000 }, controlSettings.DefaultBackground());
|
VERIFY_ARE_EQUAL(til::color{ 0xff000000 }, controlSettings.DefaultBackground());
|
||||||
VERIFY_ARE_EQUAL(originalSettings, page->_originalSettings);
|
// And we should have stored a function to revert the change.
|
||||||
|
VERIFY_ARE_EQUAL(1u, page->_restorePreviewFuncs.size());
|
||||||
});
|
});
|
||||||
|
|
||||||
TestOnUIThread([&page]() {
|
TestOnUIThread([&page]() {
|
||||||
|
@ -1383,7 +1384,8 @@ namespace TerminalAppLocalTests
|
||||||
|
|
||||||
Log::Comment(L"Color should be changed");
|
Log::Comment(L"Color should be changed");
|
||||||
VERIFY_ARE_EQUAL(til::color{ 0xff000000 }, controlSettings.DefaultBackground());
|
VERIFY_ARE_EQUAL(til::color{ 0xff000000 }, controlSettings.DefaultBackground());
|
||||||
VERIFY_ARE_EQUAL(nullptr, page->_originalSettings);
|
// After preview there should be no more restore functions to execute.
|
||||||
|
VERIFY_ARE_EQUAL(0u, page->_restorePreviewFuncs.size());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1428,7 +1430,6 @@ namespace TerminalAppLocalTests
|
||||||
|
|
||||||
Log::Comment(L"Color should be changed to the preview");
|
Log::Comment(L"Color should be changed to the preview");
|
||||||
VERIFY_ARE_EQUAL(til::color{ 0xff000000 }, controlSettings.DefaultBackground());
|
VERIFY_ARE_EQUAL(til::color{ 0xff000000 }, controlSettings.DefaultBackground());
|
||||||
VERIFY_ARE_EQUAL(originalSettings, page->_originalSettings);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
TestOnUIThread([&page]() {
|
TestOnUIThread([&page]() {
|
||||||
|
@ -1451,7 +1452,6 @@ namespace TerminalAppLocalTests
|
||||||
|
|
||||||
Log::Comment(L"Color should be the same as it originally was");
|
Log::Comment(L"Color should be the same as it originally was");
|
||||||
VERIFY_ARE_EQUAL(til::color{ 0xff0c0c0c }, controlSettings.DefaultBackground());
|
VERIFY_ARE_EQUAL(til::color{ 0xff0c0c0c }, controlSettings.DefaultBackground());
|
||||||
VERIFY_ARE_EQUAL(nullptr, page->_originalSettings);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1498,7 +1498,6 @@ namespace TerminalAppLocalTests
|
||||||
|
|
||||||
Log::Comment(L"Color should be changed to the preview");
|
Log::Comment(L"Color should be changed to the preview");
|
||||||
VERIFY_ARE_EQUAL(til::color{ 0xff000000 }, controlSettings.DefaultBackground());
|
VERIFY_ARE_EQUAL(til::color{ 0xff000000 }, controlSettings.DefaultBackground());
|
||||||
VERIFY_ARE_EQUAL(originalSettings, page->_originalSettings);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
TestOnUIThread([&page]() {
|
TestOnUIThread([&page]() {
|
||||||
|
@ -1522,7 +1521,6 @@ namespace TerminalAppLocalTests
|
||||||
|
|
||||||
Log::Comment(L"Color should be changed to the preview");
|
Log::Comment(L"Color should be changed to the preview");
|
||||||
VERIFY_ARE_EQUAL(til::color{ 0xffFAFAFA }, controlSettings.DefaultBackground());
|
VERIFY_ARE_EQUAL(til::color{ 0xffFAFAFA }, controlSettings.DefaultBackground());
|
||||||
VERIFY_ARE_EQUAL(originalSettings, page->_originalSettings);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
TestOnUIThread([&page]() {
|
TestOnUIThread([&page]() {
|
||||||
|
@ -1548,7 +1546,6 @@ namespace TerminalAppLocalTests
|
||||||
|
|
||||||
Log::Comment(L"Color should be changed");
|
Log::Comment(L"Color should be changed");
|
||||||
VERIFY_ARE_EQUAL(til::color{ 0xffFAFAFA }, controlSettings.DefaultBackground());
|
VERIFY_ARE_EQUAL(til::color{ 0xffFAFAFA }, controlSettings.DefaultBackground());
|
||||||
VERIFY_ARE_EQUAL(nullptr, page->_originalSettings);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
5
src/cascadia/Remoting/GetWindowLayoutArgs.cpp
Normal file
5
src/cascadia/Remoting/GetWindowLayoutArgs.cpp
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
// Copyright (c) Microsoft Corporation.
|
||||||
|
// Licensed under the MIT license.
|
||||||
|
#include "pch.h"
|
||||||
|
#include "GetWindowLayoutArgs.h"
|
||||||
|
#include "GetWindowLayoutArgs.g.cpp"
|
32
src/cascadia/Remoting/GetWindowLayoutArgs.h
Normal file
32
src/cascadia/Remoting/GetWindowLayoutArgs.h
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
/*++
|
||||||
|
Copyright (c) Microsoft Corporation
|
||||||
|
Licensed under the MIT license.
|
||||||
|
|
||||||
|
Class Name:
|
||||||
|
- GetWindowLayoutArgs.h
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
- This is a helper class for getting the window layout from a peasant.
|
||||||
|
Depending on if we are running on the monarch or on a peasant we might need
|
||||||
|
to switch what thread we are executing on. This gives us the option of
|
||||||
|
either returning the json result synchronously, or as a promise.
|
||||||
|
--*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "GetWindowLayoutArgs.g.h"
|
||||||
|
#include "../cascadia/inc/cppwinrt_utils.h"
|
||||||
|
|
||||||
|
namespace winrt::Microsoft::Terminal::Remoting::implementation
|
||||||
|
{
|
||||||
|
struct GetWindowLayoutArgs : public GetWindowLayoutArgsT<GetWindowLayoutArgs>
|
||||||
|
{
|
||||||
|
WINRT_PROPERTY(winrt::hstring, WindowLayoutJson, L"");
|
||||||
|
WINRT_PROPERTY(winrt::Windows::Foundation::IAsyncOperation<winrt::hstring>, WindowLayoutJsonAsync, nullptr)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace winrt::Microsoft::Terminal::Remoting::factory_implementation
|
||||||
|
{
|
||||||
|
BASIC_FACTORY(GetWindowLayoutArgs);
|
||||||
|
}
|
|
@ -12,7 +12,6 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
|
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
|
||||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
|
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
|
||||||
|
|
||||||
<!-- ========================= Headers ======================== -->
|
<!-- ========================= Headers ======================== -->
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="Monarch.h">
|
<ClInclude Include="Monarch.h">
|
||||||
|
@ -36,6 +35,12 @@
|
||||||
<ClInclude Include="WindowActivatedArgs.h">
|
<ClInclude Include="WindowActivatedArgs.h">
|
||||||
<DependentUpon>Peasant.idl</DependentUpon>
|
<DependentUpon>Peasant.idl</DependentUpon>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="GetWindowLayoutArgs.h">
|
||||||
|
<DependentUpon>Peasant.idl</DependentUpon>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="QuitAllRequestedArgs.h">
|
||||||
|
<DependentUpon>Monarch.idl</DependentUpon>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="pch.h" />
|
<ClInclude Include="pch.h" />
|
||||||
<ClInclude Include="MonarchFactory.h" />
|
<ClInclude Include="MonarchFactory.h" />
|
||||||
<ClInclude Include="Peasant.h">
|
<ClInclude Include="Peasant.h">
|
||||||
|
@ -71,6 +76,12 @@
|
||||||
<ClCompile Include="WindowActivatedArgs.cpp">
|
<ClCompile Include="WindowActivatedArgs.cpp">
|
||||||
<DependentUpon>Peasant.idl</DependentUpon>
|
<DependentUpon>Peasant.idl</DependentUpon>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="GetWindowLayoutArgs.cpp">
|
||||||
|
<DependentUpon>Peasant.idl</DependentUpon>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="QuitAllRequestedArgs.cpp">
|
||||||
|
<DependentUpon>Monarch.idl</DependentUpon>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="pch.cpp">
|
<ClCompile Include="pch.cpp">
|
||||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -128,6 +139,5 @@
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<!-- ========================= Globals ======================== -->
|
<!-- ========================= Globals ======================== -->
|
||||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
|
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
|
||||||
|
|
||||||
<Import Project="$(SolutionDir)build\rules\CollectWildcardResources.targets" />
|
<Import Project="$(SolutionDir)build\rules\CollectWildcardResources.targets" />
|
||||||
</Project>
|
</Project>
|
|
@ -6,6 +6,7 @@
|
||||||
#include "Monarch.h"
|
#include "Monarch.h"
|
||||||
#include "CommandlineArgs.h"
|
#include "CommandlineArgs.h"
|
||||||
#include "FindTargetWindowArgs.h"
|
#include "FindTargetWindowArgs.h"
|
||||||
|
#include "QuitAllRequestedArgs.h"
|
||||||
#include "ProposeCommandlineResult.h"
|
#include "ProposeCommandlineResult.h"
|
||||||
|
|
||||||
#include "Monarch.g.cpp"
|
#include "Monarch.g.cpp"
|
||||||
|
@ -135,12 +136,18 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
||||||
// - <none> used
|
// - <none> used
|
||||||
// Return Value:
|
// Return Value:
|
||||||
// - <none>
|
// - <none>
|
||||||
void Monarch::_handleQuitAll(const winrt::Windows::Foundation::IInspectable& /*sender*/,
|
winrt::fire_and_forget Monarch::_handleQuitAll(const winrt::Windows::Foundation::IInspectable& /*sender*/,
|
||||||
const winrt::Windows::Foundation::IInspectable& /*args*/)
|
const winrt::Windows::Foundation::IInspectable& /*args*/)
|
||||||
{
|
{
|
||||||
// Let the process hosting the monarch run any needed logic before
|
// Let the process hosting the monarch run any needed logic before
|
||||||
// closing all windows.
|
// closing all windows.
|
||||||
_QuitAllRequestedHandlers(*this, nullptr);
|
auto args = winrt::make_self<implementation::QuitAllRequestedArgs>();
|
||||||
|
_QuitAllRequestedHandlers(*this, *args);
|
||||||
|
|
||||||
|
if (const auto action = args->BeforeQuitAllAction())
|
||||||
|
{
|
||||||
|
co_await action;
|
||||||
|
}
|
||||||
|
|
||||||
_quitting.store(true);
|
_quitting.store(true);
|
||||||
// Tell all peasants to exit.
|
// Tell all peasants to exit.
|
||||||
|
@ -994,4 +1001,28 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
||||||
|
|
||||||
_forEachPeasant(func, onError);
|
_forEachPeasant(func, onError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Method Description:
|
||||||
|
// - Ask all peasants to return their window layout as json
|
||||||
|
// Arguments:
|
||||||
|
// - <none>
|
||||||
|
// Return Value:
|
||||||
|
// - The collection of window layouts from each peasant.
|
||||||
|
Windows::Foundation::Collections::IVector<winrt::hstring> Monarch::GetAllWindowLayouts()
|
||||||
|
{
|
||||||
|
std::vector<winrt::hstring> vec;
|
||||||
|
auto callback = [&](const auto& /*id*/, const auto& p) {
|
||||||
|
vec.emplace_back(p.GetWindowLayout());
|
||||||
|
};
|
||||||
|
auto onError = [](auto&& id) {
|
||||||
|
TraceLoggingWrite(g_hRemotingProvider,
|
||||||
|
"Monarch_GetAllWindowLayouts_Failed",
|
||||||
|
TraceLoggingInt64(id, "peasantID", "The ID of the peasant which we could not get a window layout from"),
|
||||||
|
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
|
||||||
|
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
||||||
|
};
|
||||||
|
_forEachPeasant(callback, onError);
|
||||||
|
|
||||||
|
return winrt::single_threaded_vector(std::move(vec));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,13 +59,14 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
||||||
void SummonAllWindows();
|
void SummonAllWindows();
|
||||||
bool DoesQuakeWindowExist();
|
bool DoesQuakeWindowExist();
|
||||||
Windows::Foundation::Collections::IVectorView<winrt::Microsoft::Terminal::Remoting::PeasantInfo> GetPeasantInfos();
|
Windows::Foundation::Collections::IVectorView<winrt::Microsoft::Terminal::Remoting::PeasantInfo> GetPeasantInfos();
|
||||||
|
Windows::Foundation::Collections::IVector<winrt::hstring> GetAllWindowLayouts();
|
||||||
|
|
||||||
TYPED_EVENT(FindTargetWindowRequested, winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::FindTargetWindowArgs);
|
TYPED_EVENT(FindTargetWindowRequested, winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::FindTargetWindowArgs);
|
||||||
TYPED_EVENT(ShowNotificationIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
TYPED_EVENT(ShowNotificationIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||||
TYPED_EVENT(HideNotificationIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
TYPED_EVENT(HideNotificationIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||||
TYPED_EVENT(WindowCreated, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
TYPED_EVENT(WindowCreated, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||||
TYPED_EVENT(WindowClosed, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
TYPED_EVENT(WindowClosed, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||||
TYPED_EVENT(QuitAllRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
TYPED_EVENT(QuitAllRequested, winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::QuitAllRequestedArgs);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint64_t _ourPID;
|
uint64_t _ourPID;
|
||||||
|
@ -103,8 +104,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
||||||
void _renameRequested(const winrt::Windows::Foundation::IInspectable& sender,
|
void _renameRequested(const winrt::Windows::Foundation::IInspectable& sender,
|
||||||
const winrt::Microsoft::Terminal::Remoting::RenameRequestArgs& args);
|
const winrt::Microsoft::Terminal::Remoting::RenameRequestArgs& args);
|
||||||
|
|
||||||
void _handleQuitAll(const winrt::Windows::Foundation::IInspectable& sender,
|
winrt::fire_and_forget _handleQuitAll(const winrt::Windows::Foundation::IInspectable& sender,
|
||||||
const winrt::Windows::Foundation::IInspectable& args);
|
const winrt::Windows::Foundation::IInspectable& args);
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
// - Helper for doing something on each and every peasant.
|
// - Helper for doing something on each and every peasant.
|
||||||
|
@ -177,6 +178,10 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_clearOldMruEntries(peasantsToErase);
|
_clearOldMruEntries(peasantsToErase);
|
||||||
|
|
||||||
|
// A peasant died, let the app host know that the number of
|
||||||
|
// windows has changed.
|
||||||
|
_WindowClosedHandlers(nullptr, nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,12 @@ namespace Microsoft.Terminal.Remoting
|
||||||
Windows.Foundation.IReference<UInt64> WindowID;
|
Windows.Foundation.IReference<UInt64> WindowID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[default_interface] runtimeclass QuitAllRequestedArgs
|
||||||
|
{
|
||||||
|
QuitAllRequestedArgs();
|
||||||
|
Windows.Foundation.IAsyncAction BeforeQuitAllAction;
|
||||||
|
}
|
||||||
|
|
||||||
struct PeasantInfo
|
struct PeasantInfo
|
||||||
{
|
{
|
||||||
UInt64 Id;
|
UInt64 Id;
|
||||||
|
@ -52,12 +58,13 @@ namespace Microsoft.Terminal.Remoting
|
||||||
void SummonAllWindows();
|
void SummonAllWindows();
|
||||||
Boolean DoesQuakeWindowExist();
|
Boolean DoesQuakeWindowExist();
|
||||||
Windows.Foundation.Collections.IVectorView<PeasantInfo> GetPeasantInfos { get; };
|
Windows.Foundation.Collections.IVectorView<PeasantInfo> GetPeasantInfos { get; };
|
||||||
|
Windows.Foundation.Collections.IVector<String> GetAllWindowLayouts();
|
||||||
|
|
||||||
event Windows.Foundation.TypedEventHandler<Object, FindTargetWindowArgs> FindTargetWindowRequested;
|
event Windows.Foundation.TypedEventHandler<Object, FindTargetWindowArgs> FindTargetWindowRequested;
|
||||||
event Windows.Foundation.TypedEventHandler<Object, Object> ShowNotificationIconRequested;
|
event Windows.Foundation.TypedEventHandler<Object, Object> ShowNotificationIconRequested;
|
||||||
event Windows.Foundation.TypedEventHandler<Object, Object> HideNotificationIconRequested;
|
event Windows.Foundation.TypedEventHandler<Object, Object> HideNotificationIconRequested;
|
||||||
event Windows.Foundation.TypedEventHandler<Object, Object> WindowCreated;
|
event Windows.Foundation.TypedEventHandler<Object, Object> WindowCreated;
|
||||||
event Windows.Foundation.TypedEventHandler<Object, Object> WindowClosed;
|
event Windows.Foundation.TypedEventHandler<Object, Object> WindowClosed;
|
||||||
event Windows.Foundation.TypedEventHandler<Object, Object> QuitAllRequested;
|
event Windows.Foundation.TypedEventHandler<Object, QuitAllRequestedArgs> QuitAllRequested;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "Peasant.h"
|
#include "Peasant.h"
|
||||||
#include "CommandlineArgs.h"
|
#include "CommandlineArgs.h"
|
||||||
#include "SummonWindowBehavior.h"
|
#include "SummonWindowBehavior.h"
|
||||||
|
#include "GetWindowLayoutArgs.h"
|
||||||
#include "Peasant.g.cpp"
|
#include "Peasant.g.cpp"
|
||||||
#include "../../types/inc/utils.hpp"
|
#include "../../types/inc/utils.hpp"
|
||||||
|
|
||||||
|
@ -289,4 +290,24 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
||||||
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
|
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
|
||||||
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Method Description:
|
||||||
|
// - Request and return the window layout from the current TerminalPage
|
||||||
|
// Arguments:
|
||||||
|
// - <none>
|
||||||
|
// Return Value:
|
||||||
|
// - the window layout as a json string
|
||||||
|
hstring Peasant::GetWindowLayout()
|
||||||
|
{
|
||||||
|
auto args = winrt::make_self<implementation::GetWindowLayoutArgs>();
|
||||||
|
_GetWindowLayoutRequestedHandlers(nullptr, *args);
|
||||||
|
if (const auto op = args->WindowLayoutJsonAsync())
|
||||||
|
{
|
||||||
|
// This will fail if called on the UI thread, so the monarch should
|
||||||
|
// never set WindowLayoutJsonAsync.
|
||||||
|
auto str = op.get();
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
return args->WindowLayoutJson();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,9 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
||||||
winrt::Microsoft::Terminal::Remoting::WindowActivatedArgs GetLastActivatedArgs();
|
winrt::Microsoft::Terminal::Remoting::WindowActivatedArgs GetLastActivatedArgs();
|
||||||
|
|
||||||
winrt::Microsoft::Terminal::Remoting::CommandlineArgs InitialArgs();
|
winrt::Microsoft::Terminal::Remoting::CommandlineArgs InitialArgs();
|
||||||
|
|
||||||
|
winrt::hstring GetWindowLayout();
|
||||||
|
|
||||||
WINRT_PROPERTY(winrt::hstring, WindowName);
|
WINRT_PROPERTY(winrt::hstring, WindowName);
|
||||||
WINRT_PROPERTY(winrt::hstring, ActiveTabTitle);
|
WINRT_PROPERTY(winrt::hstring, ActiveTabTitle);
|
||||||
|
|
||||||
|
@ -49,6 +52,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
||||||
TYPED_EVENT(HideNotificationIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
TYPED_EVENT(HideNotificationIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||||
TYPED_EVENT(QuitAllRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
TYPED_EVENT(QuitAllRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||||
TYPED_EVENT(QuitRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
TYPED_EVENT(QuitRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||||
|
TYPED_EVENT(GetWindowLayoutRequested, winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::GetWindowLayoutArgs);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Peasant(const uint64_t testPID);
|
Peasant(const uint64_t testPID);
|
||||||
|
|
|
@ -30,6 +30,11 @@ namespace Microsoft.Terminal.Remoting
|
||||||
Windows.Foundation.DateTime ActivatedTime { get; };
|
Windows.Foundation.DateTime ActivatedTime { get; };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
[default_interface] runtimeclass GetWindowLayoutArgs {
|
||||||
|
GetWindowLayoutArgs();
|
||||||
|
String WindowLayoutJson;
|
||||||
|
Windows.Foundation.IAsyncOperation<String> WindowLayoutJsonAsync;
|
||||||
|
}
|
||||||
|
|
||||||
enum MonitorBehavior
|
enum MonitorBehavior
|
||||||
{
|
{
|
||||||
|
@ -69,6 +74,7 @@ namespace Microsoft.Terminal.Remoting
|
||||||
void RequestHideNotificationIcon();
|
void RequestHideNotificationIcon();
|
||||||
void RequestQuitAll();
|
void RequestQuitAll();
|
||||||
void Quit();
|
void Quit();
|
||||||
|
String GetWindowLayout();
|
||||||
|
|
||||||
event Windows.Foundation.TypedEventHandler<Object, WindowActivatedArgs> WindowActivated;
|
event Windows.Foundation.TypedEventHandler<Object, WindowActivatedArgs> WindowActivated;
|
||||||
event Windows.Foundation.TypedEventHandler<Object, CommandlineArgs> ExecuteCommandlineRequested;
|
event Windows.Foundation.TypedEventHandler<Object, CommandlineArgs> ExecuteCommandlineRequested;
|
||||||
|
@ -78,6 +84,7 @@ namespace Microsoft.Terminal.Remoting
|
||||||
event Windows.Foundation.TypedEventHandler<Object, SummonWindowBehavior> SummonRequested;
|
event Windows.Foundation.TypedEventHandler<Object, SummonWindowBehavior> SummonRequested;
|
||||||
event Windows.Foundation.TypedEventHandler<Object, Object> ShowNotificationIconRequested;
|
event Windows.Foundation.TypedEventHandler<Object, Object> ShowNotificationIconRequested;
|
||||||
event Windows.Foundation.TypedEventHandler<Object, Object> HideNotificationIconRequested;
|
event Windows.Foundation.TypedEventHandler<Object, Object> HideNotificationIconRequested;
|
||||||
|
event Windows.Foundation.TypedEventHandler<Object, GetWindowLayoutArgs> GetWindowLayoutRequested;
|
||||||
event Windows.Foundation.TypedEventHandler<Object, Object> QuitAllRequested;
|
event Windows.Foundation.TypedEventHandler<Object, Object> QuitAllRequested;
|
||||||
event Windows.Foundation.TypedEventHandler<Object, Object> QuitRequested;
|
event Windows.Foundation.TypedEventHandler<Object, Object> QuitRequested;
|
||||||
};
|
};
|
||||||
|
|
5
src/cascadia/Remoting/QuitAllRequestedArgs.cpp
Normal file
5
src/cascadia/Remoting/QuitAllRequestedArgs.cpp
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
// Copyright (c) Microsoft Corporation.
|
||||||
|
// Licensed under the MIT license.
|
||||||
|
#include "pch.h"
|
||||||
|
#include "QuitAllRequestedArgs.h"
|
||||||
|
#include "QuitAllRequestedArgs.g.cpp"
|
30
src/cascadia/Remoting/QuitAllRequestedArgs.h
Normal file
30
src/cascadia/Remoting/QuitAllRequestedArgs.h
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
/*++
|
||||||
|
Copyright (c) Microsoft Corporation
|
||||||
|
Licensed under the MIT license.
|
||||||
|
|
||||||
|
Class Name:
|
||||||
|
- QuitAllRequestedArgs.h
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
- This is a helper class for allowing the monarch to run code before telling all
|
||||||
|
peasants to quit. This way the monarch can raise an event and get back a future
|
||||||
|
to wait for before continuing.
|
||||||
|
--*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "QuitAllRequestedArgs.g.h"
|
||||||
|
#include "../cascadia/inc/cppwinrt_utils.h"
|
||||||
|
|
||||||
|
namespace winrt::Microsoft::Terminal::Remoting::implementation
|
||||||
|
{
|
||||||
|
struct QuitAllRequestedArgs : public QuitAllRequestedArgsT<QuitAllRequestedArgs>
|
||||||
|
{
|
||||||
|
WINRT_PROPERTY(winrt::Windows::Foundation::IAsyncAction, BeforeQuitAllAction, nullptr)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace winrt::Microsoft::Terminal::Remoting::factory_implementation
|
||||||
|
{
|
||||||
|
BASIC_FACTORY(QuitAllRequestedArgs);
|
||||||
|
}
|
|
@ -271,7 +271,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
||||||
_monarch.FindTargetWindowRequested({ this, &WindowManager::_raiseFindTargetWindowRequested });
|
_monarch.FindTargetWindowRequested({ this, &WindowManager::_raiseFindTargetWindowRequested });
|
||||||
_monarch.ShowNotificationIconRequested([this](auto&&, auto&&) { _ShowNotificationIconRequestedHandlers(*this, nullptr); });
|
_monarch.ShowNotificationIconRequested([this](auto&&, auto&&) { _ShowNotificationIconRequestedHandlers(*this, nullptr); });
|
||||||
_monarch.HideNotificationIconRequested([this](auto&&, auto&&) { _HideNotificationIconRequestedHandlers(*this, nullptr); });
|
_monarch.HideNotificationIconRequested([this](auto&&, auto&&) { _HideNotificationIconRequestedHandlers(*this, nullptr); });
|
||||||
_monarch.QuitAllRequested([this](auto&&, auto&&) { _QuitAllRequestedHandlers(*this, nullptr); });
|
_monarch.QuitAllRequested({ get_weak(), &WindowManager::_QuitAllRequestedHandlers });
|
||||||
|
|
||||||
_BecameMonarchHandlers(*this, nullptr);
|
_BecameMonarchHandlers(*this, nullptr);
|
||||||
}
|
}
|
||||||
|
@ -318,6 +318,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_peasant.GetWindowLayoutRequested({ get_weak(), &WindowManager::_GetWindowLayoutRequestedHandlers });
|
||||||
|
|
||||||
TraceLoggingWrite(g_hRemotingProvider,
|
TraceLoggingWrite(g_hRemotingProvider,
|
||||||
"WindowManager_CreateOurPeasant",
|
"WindowManager_CreateOurPeasant",
|
||||||
TraceLoggingUInt64(_peasant.GetID(), "peasantID", "The ID of our new peasant"),
|
TraceLoggingUInt64(_peasant.GetID(), "peasantID", "The ID of our new peasant"),
|
||||||
|
@ -610,4 +612,17 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
||||||
{
|
{
|
||||||
winrt::get_self<implementation::Peasant>(_peasant)->ActiveTabTitle(title);
|
winrt::get_self<implementation::Peasant>(_peasant)->ActiveTabTitle(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Windows::Foundation::Collections::IVector<winrt::hstring> WindowManager::GetAllWindowLayouts()
|
||||||
|
{
|
||||||
|
if (_monarch)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return _monarch.GetAllWindowLayouts();
|
||||||
|
}
|
||||||
|
CATCH_LOG()
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,6 +50,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
||||||
winrt::fire_and_forget RequestQuitAll();
|
winrt::fire_and_forget RequestQuitAll();
|
||||||
bool DoesQuakeWindowExist();
|
bool DoesQuakeWindowExist();
|
||||||
void UpdateActiveTabTitle(winrt::hstring title);
|
void UpdateActiveTabTitle(winrt::hstring title);
|
||||||
|
Windows::Foundation::Collections::IVector<winrt::hstring> GetAllWindowLayouts();
|
||||||
|
|
||||||
TYPED_EVENT(FindTargetWindowRequested, winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::FindTargetWindowArgs);
|
TYPED_EVENT(FindTargetWindowRequested, winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::FindTargetWindowArgs);
|
||||||
TYPED_EVENT(BecameMonarch, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
TYPED_EVENT(BecameMonarch, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||||
|
@ -57,7 +58,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
||||||
TYPED_EVENT(WindowClosed, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
TYPED_EVENT(WindowClosed, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||||
TYPED_EVENT(ShowNotificationIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
TYPED_EVENT(ShowNotificationIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||||
TYPED_EVENT(HideNotificationIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
TYPED_EVENT(HideNotificationIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||||
TYPED_EVENT(QuitAllRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
TYPED_EVENT(QuitAllRequested, winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::QuitAllRequestedArgs);
|
||||||
|
TYPED_EVENT(GetWindowLayoutRequested, winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::GetWindowLayoutArgs);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool _shouldCreateWindow{ false };
|
bool _shouldCreateWindow{ false };
|
||||||
|
|
|
@ -16,6 +16,8 @@ namespace Microsoft.Terminal.Remoting
|
||||||
void SummonAllWindows();
|
void SummonAllWindows();
|
||||||
void RequestShowNotificationIcon();
|
void RequestShowNotificationIcon();
|
||||||
void RequestHideNotificationIcon();
|
void RequestHideNotificationIcon();
|
||||||
|
Windows.Foundation.Collections.IVector<String> GetAllWindowLayouts();
|
||||||
|
|
||||||
UInt64 GetNumberOfPeasants();
|
UInt64 GetNumberOfPeasants();
|
||||||
void RequestQuitAll();
|
void RequestQuitAll();
|
||||||
void UpdateActiveTabTitle(String title);
|
void UpdateActiveTabTitle(String title);
|
||||||
|
@ -25,8 +27,9 @@ namespace Microsoft.Terminal.Remoting
|
||||||
event Windows.Foundation.TypedEventHandler<Object, Object> BecameMonarch;
|
event Windows.Foundation.TypedEventHandler<Object, Object> BecameMonarch;
|
||||||
event Windows.Foundation.TypedEventHandler<Object, Object> WindowCreated;
|
event Windows.Foundation.TypedEventHandler<Object, Object> WindowCreated;
|
||||||
event Windows.Foundation.TypedEventHandler<Object, Object> WindowClosed;
|
event Windows.Foundation.TypedEventHandler<Object, Object> WindowClosed;
|
||||||
|
event Windows.Foundation.TypedEventHandler<Object, QuitAllRequestedArgs> QuitAllRequested;
|
||||||
|
event Windows.Foundation.TypedEventHandler<Object, GetWindowLayoutArgs> GetWindowLayoutRequested;
|
||||||
event Windows.Foundation.TypedEventHandler<Object, Object> ShowNotificationIconRequested;
|
event Windows.Foundation.TypedEventHandler<Object, Object> ShowNotificationIconRequested;
|
||||||
event Windows.Foundation.TypedEventHandler<Object, Object> HideNotificationIconRequested;
|
event Windows.Foundation.TypedEventHandler<Object, Object> HideNotificationIconRequested;
|
||||||
event Windows.Foundation.TypedEventHandler<Object, Object> QuitAllRequested;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,9 +55,7 @@ HRESULT OpenTerminalHere::Invoke(IShellItemArray* psiItemArray,
|
||||||
STARTUPINFOEX siEx{ 0 };
|
STARTUPINFOEX siEx{ 0 };
|
||||||
siEx.StartupInfo.cb = sizeof(STARTUPINFOEX);
|
siEx.StartupInfo.cb = sizeof(STARTUPINFOEX);
|
||||||
|
|
||||||
// Append a "\." to the given path, so that this will work in "C:\"
|
auto cmdline{ wil::str_printf<std::wstring>(LR"-("%s" -d %s)-", GetWtExePath().c_str(), QuoteAndEscapeCommandlineArg(pszName.get()).c_str()) };
|
||||||
auto path{ wil::str_printf<std::wstring>(LR"-(%s\.)-", pszName.get()) };
|
|
||||||
auto cmdline{ wil::str_printf<std::wstring>(LR"-("%s" -d "%s")-", GetWtExePath().c_str(), path.c_str()) };
|
|
||||||
RETURN_IF_WIN32_BOOL_FALSE(CreateProcessW(
|
RETURN_IF_WIN32_BOOL_FALSE(CreateProcessW(
|
||||||
nullptr, // lpApplicationName
|
nullptr, // lpApplicationName
|
||||||
cmdline.data(),
|
cmdline.data(),
|
||||||
|
@ -66,7 +64,7 @@ HRESULT OpenTerminalHere::Invoke(IShellItemArray* psiItemArray,
|
||||||
false, // bInheritHandles
|
false, // bInheritHandles
|
||||||
EXTENDED_STARTUPINFO_PRESENT | CREATE_UNICODE_ENVIRONMENT, // dwCreationFlags
|
EXTENDED_STARTUPINFO_PRESENT | CREATE_UNICODE_ENVIRONMENT, // dwCreationFlags
|
||||||
nullptr, // lpEnvironment
|
nullptr, // lpEnvironment
|
||||||
path.data(),
|
pszName.get(),
|
||||||
&siEx.StartupInfo, // lpStartupInfo
|
&siEx.StartupInfo, // lpStartupInfo
|
||||||
&_piClient // lpProcessInformation
|
&_piClient // lpProcessInformation
|
||||||
));
|
));
|
||||||
|
|
|
@ -67,41 +67,17 @@ namespace winrt::TerminalApp::implementation
|
||||||
// - <none>
|
// - <none>
|
||||||
void TerminalPage::_EndPreviewColorScheme()
|
void TerminalPage::_EndPreviewColorScheme()
|
||||||
{
|
{
|
||||||
// Get the focused control
|
for (const auto& f : _restorePreviewFuncs)
|
||||||
if (const auto& activeControl{ _GetActiveControl() })
|
|
||||||
{
|
{
|
||||||
// Get the runtime settings of the focused control
|
f();
|
||||||
const auto& controlSettings{ activeControl.Settings().as<TerminalSettings>() };
|
|
||||||
|
|
||||||
// Get the control's root settings, the ones that we actually
|
|
||||||
// assigned to it.
|
|
||||||
auto parentSettings{ controlSettings.GetParent() };
|
|
||||||
while (parentSettings.GetParent() != nullptr)
|
|
||||||
{
|
|
||||||
parentSettings = parentSettings.GetParent();
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the root settings are the same as the ones we stashed,
|
|
||||||
// then reset the parent of the runtime settings to the stashed
|
|
||||||
// settings. This condition might be false if the settings
|
|
||||||
// hot-reloaded while the palette was open. In that case, we
|
|
||||||
// don't want to reset the settings to what they were _before_
|
|
||||||
// the hot-reload.
|
|
||||||
if (_originalSettings == parentSettings)
|
|
||||||
{
|
|
||||||
// Set the original settings as the parent of the control's settings
|
|
||||||
activeControl.Settings().as<TerminalSettings>().SetParent(_originalSettings);
|
|
||||||
}
|
|
||||||
|
|
||||||
activeControl.UpdateSettings();
|
|
||||||
}
|
}
|
||||||
_originalSettings = nullptr;
|
_restorePreviewFuncs.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
// - Preview handler for the SetColorScheme action.
|
// - Preview handler for the SetColorScheme action.
|
||||||
// - This method will stash the settings of the current control in
|
// - This method will stash functions to reset the settings of the selected controls in
|
||||||
// _originalSettings. Then it will create a new TerminalSettings object
|
// _restorePreviewFuncs. Then it will create a new TerminalSettings object
|
||||||
// with only the properties from the ColorScheme set. It'll _insert_ a
|
// with only the properties from the ColorScheme set. It'll _insert_ a
|
||||||
// TerminalSettings between the control's root settings (built from
|
// TerminalSettings between the control's root settings (built from
|
||||||
// CascadiaSettings) and the control's runtime settings. That'll cause the
|
// CascadiaSettings) and the control's runtime settings. That'll cause the
|
||||||
|
@ -112,33 +88,63 @@ namespace winrt::TerminalApp::implementation
|
||||||
// - <none>
|
// - <none>
|
||||||
void TerminalPage::_PreviewColorScheme(const Settings::Model::SetColorSchemeArgs& args)
|
void TerminalPage::_PreviewColorScheme(const Settings::Model::SetColorSchemeArgs& args)
|
||||||
{
|
{
|
||||||
// Get the focused control
|
if (const auto& scheme{ _settings.GlobalSettings().ColorSchemes().TryLookup(args.SchemeName()) })
|
||||||
if (const auto& activeControl{ _GetActiveControl() })
|
|
||||||
{
|
{
|
||||||
if (const auto& scheme{ _settings.GlobalSettings().ColorSchemes().TryLookup(args.SchemeName()) })
|
// Clear the saved preview funcs because we don't need to add a restore each time
|
||||||
{
|
// the preview color changes, we only need to be able to restore the last one.
|
||||||
|
_restorePreviewFuncs.clear();
|
||||||
|
|
||||||
|
_ApplyToActiveControls([&](const auto& control) {
|
||||||
// Get the settings of the focused control and stash them
|
// Get the settings of the focused control and stash them
|
||||||
const auto& controlSettings = activeControl.Settings().as<TerminalSettings>();
|
const auto& controlSettings = control.Settings().as<TerminalSettings>();
|
||||||
// Make sure to recurse up to the root - if you're doing
|
// Make sure to recurse up to the root - if you're doing
|
||||||
// this while you're currently previewing a SetColorScheme
|
// this while you're currently previewing a SetColorScheme
|
||||||
// action, then the parent of the control's settings is _the
|
// action, then the parent of the control's settings is _the
|
||||||
// last preview TerminalSettings we inserted! We don't want
|
// last preview TerminalSettings we inserted! We don't want
|
||||||
// to save that one!
|
// to save that one!
|
||||||
_originalSettings = controlSettings.GetParent();
|
auto originalSettings = controlSettings.GetParent();
|
||||||
while (_originalSettings.GetParent() != nullptr)
|
while (originalSettings.GetParent() != nullptr)
|
||||||
{
|
{
|
||||||
_originalSettings = _originalSettings.GetParent();
|
originalSettings = originalSettings.GetParent();
|
||||||
}
|
}
|
||||||
// Create a new child for those settings
|
// Create a new child for those settings
|
||||||
TerminalSettingsCreateResult fake{ _originalSettings };
|
TerminalSettingsCreateResult fake{ originalSettings };
|
||||||
const auto& childStruct = TerminalSettings::CreateWithParent(fake);
|
const auto& childStruct = TerminalSettings::CreateWithParent(fake);
|
||||||
// Modify the child to have the applied color scheme
|
// Modify the child to have the applied color scheme
|
||||||
childStruct.DefaultSettings().ApplyColorScheme(scheme);
|
childStruct.DefaultSettings().ApplyColorScheme(scheme);
|
||||||
|
|
||||||
// Insert that new child as the parent of the control's settings
|
// Insert that new child as the parent of the control's settings
|
||||||
controlSettings.SetParent(childStruct.DefaultSettings());
|
controlSettings.SetParent(childStruct.DefaultSettings());
|
||||||
activeControl.UpdateSettings();
|
control.UpdateSettings();
|
||||||
}
|
|
||||||
|
// Take a copy of the inputs, since they are pointers anyways.
|
||||||
|
_restorePreviewFuncs.emplace_back([=]() {
|
||||||
|
// Get the runtime settings of the focused control
|
||||||
|
const auto& controlSettings{ control.Settings().as<TerminalSettings>() };
|
||||||
|
|
||||||
|
// Get the control's root settings, the ones that we actually
|
||||||
|
// assigned to it.
|
||||||
|
auto parentSettings{ controlSettings.GetParent() };
|
||||||
|
while (parentSettings.GetParent() != nullptr)
|
||||||
|
{
|
||||||
|
parentSettings = parentSettings.GetParent();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the root settings are the same as the ones we stashed,
|
||||||
|
// then reset the parent of the runtime settings to the stashed
|
||||||
|
// settings. This condition might be false if the settings
|
||||||
|
// hot-reloaded while the palette was open. In that case, we
|
||||||
|
// don't want to reset the settings to what they were _before_
|
||||||
|
// the hot-reload.
|
||||||
|
if (originalSettings == parentSettings)
|
||||||
|
{
|
||||||
|
// Set the original settings as the parent of the control's settings
|
||||||
|
control.Settings().as<TerminalSettings>().SetParent(originalSettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
control.UpdateSettings();
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,7 @@ namespace winrt::TerminalApp::implementation
|
||||||
void TerminalPage::_HandleCloseWindow(const IInspectable& /*sender*/,
|
void TerminalPage::_HandleCloseWindow(const IInspectable& /*sender*/,
|
||||||
const ActionEventArgs& args)
|
const ActionEventArgs& args)
|
||||||
{
|
{
|
||||||
CloseWindow(false);
|
_CloseRequestedHandlers(nullptr, nullptr);
|
||||||
args.Handled(true);
|
args.Handled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -377,11 +377,10 @@ namespace winrt::TerminalApp::implementation
|
||||||
{
|
{
|
||||||
if (const auto& realArgs = args.ActionArgs().try_as<AdjustFontSizeArgs>())
|
if (const auto& realArgs = args.ActionArgs().try_as<AdjustFontSizeArgs>())
|
||||||
{
|
{
|
||||||
if (const auto& termControl{ _GetActiveControl() })
|
const auto res = _ApplyToActiveControls([&](auto& control) {
|
||||||
{
|
control.AdjustFontSize(realArgs.Delta());
|
||||||
termControl.AdjustFontSize(realArgs.Delta());
|
});
|
||||||
args.Handled(true);
|
args.Handled(res);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -395,21 +394,19 @@ namespace winrt::TerminalApp::implementation
|
||||||
void TerminalPage::_HandleResetFontSize(const IInspectable& /*sender*/,
|
void TerminalPage::_HandleResetFontSize(const IInspectable& /*sender*/,
|
||||||
const ActionEventArgs& args)
|
const ActionEventArgs& args)
|
||||||
{
|
{
|
||||||
if (const auto& termControl{ _GetActiveControl() })
|
const auto res = _ApplyToActiveControls([](auto& control) {
|
||||||
{
|
control.ResetFontSize();
|
||||||
termControl.ResetFontSize();
|
});
|
||||||
args.Handled(true);
|
args.Handled(res);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerminalPage::_HandleToggleShaderEffects(const IInspectable& /*sender*/,
|
void TerminalPage::_HandleToggleShaderEffects(const IInspectable& /*sender*/,
|
||||||
const ActionEventArgs& args)
|
const ActionEventArgs& args)
|
||||||
{
|
{
|
||||||
if (const auto& termControl{ _GetActiveControl() })
|
const auto res = _ApplyToActiveControls([](auto& control) {
|
||||||
{
|
control.ToggleShaderEffects();
|
||||||
termControl.ToggleShaderEffects();
|
});
|
||||||
args.Handled(true);
|
args.Handled(res);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerminalPage::_HandleToggleFocusMode(const IInspectable& /*sender*/,
|
void TerminalPage::_HandleToggleFocusMode(const IInspectable& /*sender*/,
|
||||||
|
@ -452,37 +449,33 @@ namespace winrt::TerminalApp::implementation
|
||||||
args.Handled(false);
|
args.Handled(false);
|
||||||
if (const auto& realArgs = args.ActionArgs().try_as<SetColorSchemeArgs>())
|
if (const auto& realArgs = args.ActionArgs().try_as<SetColorSchemeArgs>())
|
||||||
{
|
{
|
||||||
if (const auto activeTab{ _GetFocusedTabImpl() })
|
if (const auto scheme = _settings.GlobalSettings().ColorSchemes().TryLookup(realArgs.SchemeName()))
|
||||||
{
|
{
|
||||||
if (auto activeControl = activeTab->GetActiveTerminalControl())
|
const auto res = _ApplyToActiveControls([&](auto& control) {
|
||||||
{
|
// Start by getting the current settings of the control
|
||||||
if (const auto scheme = _settings.GlobalSettings().ColorSchemes().TryLookup(realArgs.SchemeName()))
|
auto controlSettings = control.Settings().as<TerminalSettings>();
|
||||||
|
auto parentSettings = controlSettings;
|
||||||
|
// Those are the _runtime_ settings however. What we
|
||||||
|
// need to do is:
|
||||||
|
//
|
||||||
|
// 1. Blow away any colors set in the runtime settings.
|
||||||
|
// 2. Apply the color scheme to the parent settings.
|
||||||
|
//
|
||||||
|
// 1 is important to make sure that the effects of
|
||||||
|
// something like `colortool` are cleared when setting
|
||||||
|
// the scheme.
|
||||||
|
if (controlSettings.GetParent() != nullptr)
|
||||||
{
|
{
|
||||||
// Start by getting the current settings of the control
|
parentSettings = controlSettings.GetParent();
|
||||||
auto controlSettings = activeControl.Settings().as<TerminalSettings>();
|
|
||||||
auto parentSettings = controlSettings;
|
|
||||||
// Those are the _runtime_ settings however. What we
|
|
||||||
// need to do is:
|
|
||||||
//
|
|
||||||
// 1. Blow away any colors set in the runtime settings.
|
|
||||||
// 2. Apply the color scheme to the parent settings.
|
|
||||||
//
|
|
||||||
// 1 is important to make sure that the effects of
|
|
||||||
// something like `colortool` are cleared when setting
|
|
||||||
// the scheme.
|
|
||||||
if (controlSettings.GetParent() != nullptr)
|
|
||||||
{
|
|
||||||
parentSettings = controlSettings.GetParent();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ApplyColorScheme(nullptr) will clear the old color scheme.
|
|
||||||
controlSettings.ApplyColorScheme(nullptr);
|
|
||||||
parentSettings.ApplyColorScheme(scheme);
|
|
||||||
|
|
||||||
activeControl.UpdateSettings();
|
|
||||||
args.Handled(true);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
// ApplyColorScheme(nullptr) will clear the old color scheme.
|
||||||
|
controlSettings.ApplyColorScheme(nullptr);
|
||||||
|
parentSettings.ApplyColorScheme(scheme);
|
||||||
|
|
||||||
|
control.UpdateSettings();
|
||||||
|
});
|
||||||
|
args.Handled(res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -896,11 +889,10 @@ namespace winrt::TerminalApp::implementation
|
||||||
{
|
{
|
||||||
if (const auto& realArgs = args.ActionArgs().try_as<ClearBufferArgs>())
|
if (const auto& realArgs = args.ActionArgs().try_as<ClearBufferArgs>())
|
||||||
{
|
{
|
||||||
if (const auto termControl{ _GetActiveControl() })
|
const auto res = _ApplyToActiveControls([&](auto& control) {
|
||||||
{
|
control.ClearBuffer(realArgs.Clear());
|
||||||
termControl.ClearBuffer(realArgs.Clear());
|
});
|
||||||
args.Handled(true);
|
args.Handled(res);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -187,6 +187,10 @@ void AppCommandlineArgs::_buildParser()
|
||||||
_windowTarget,
|
_windowTarget,
|
||||||
RS_A(L"CmdWindowTargetArgDesc"));
|
RS_A(L"CmdWindowTargetArgDesc"));
|
||||||
|
|
||||||
|
_app.add_option("-s,--saved",
|
||||||
|
_loadPersistedLayoutIdx,
|
||||||
|
RS_A(L"CmdSavedLayoutArgDesc"));
|
||||||
|
|
||||||
// Subcommands
|
// Subcommands
|
||||||
_buildNewTabParser();
|
_buildNewTabParser();
|
||||||
_buildSplitPaneParser();
|
_buildSplitPaneParser();
|
||||||
|
@ -700,6 +704,7 @@ void AppCommandlineArgs::_resetStateToDefault()
|
||||||
_swapPaneDirection = FocusDirection::None;
|
_swapPaneDirection = FocusDirection::None;
|
||||||
|
|
||||||
_focusPaneTarget = -1;
|
_focusPaneTarget = -1;
|
||||||
|
_loadPersistedLayoutIdx = -1;
|
||||||
|
|
||||||
// DON'T clear _launchMode here! This will get called once for every
|
// DON'T clear _launchMode here! This will get called once for every
|
||||||
// subcommand, so we don't want `wt -F new-tab ; split-pane` clearing out
|
// subcommand, so we don't want `wt -F new-tab ; split-pane` clearing out
|
||||||
|
@ -915,6 +920,12 @@ void AppCommandlineArgs::ValidateStartupCommands()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
std::optional<uint32_t> AppCommandlineArgs::GetPersistedLayoutIdx() const noexcept
|
||||||
|
{
|
||||||
|
return _loadPersistedLayoutIdx >= 0 ?
|
||||||
|
std::optional{ static_cast<uint32_t>(_loadPersistedLayoutIdx) } :
|
||||||
|
std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
std::optional<winrt::Microsoft::Terminal::Settings::Model::LaunchMode> AppCommandlineArgs::GetLaunchMode() const noexcept
|
std::optional<winrt::Microsoft::Terminal::Settings::Model::LaunchMode> AppCommandlineArgs::GetLaunchMode() const noexcept
|
||||||
{
|
{
|
||||||
|
|
|
@ -39,6 +39,7 @@ public:
|
||||||
const std::string& GetExitMessage();
|
const std::string& GetExitMessage();
|
||||||
bool ShouldExitEarly() const noexcept;
|
bool ShouldExitEarly() const noexcept;
|
||||||
|
|
||||||
|
std::optional<uint32_t> GetPersistedLayoutIdx() const noexcept;
|
||||||
std::optional<winrt::Microsoft::Terminal::Settings::Model::LaunchMode> GetLaunchMode() const noexcept;
|
std::optional<winrt::Microsoft::Terminal::Settings::Model::LaunchMode> GetLaunchMode() const noexcept;
|
||||||
|
|
||||||
int ParseArgs(const winrt::Microsoft::Terminal::Settings::Model::ExecuteCommandlineArgs& args);
|
int ParseArgs(const winrt::Microsoft::Terminal::Settings::Model::ExecuteCommandlineArgs& args);
|
||||||
|
@ -123,6 +124,7 @@ private:
|
||||||
std::string _exitMessage;
|
std::string _exitMessage;
|
||||||
bool _shouldExitEarly{ false };
|
bool _shouldExitEarly{ false };
|
||||||
|
|
||||||
|
int _loadPersistedLayoutIdx{};
|
||||||
std::string _windowTarget{};
|
std::string _windowTarget{};
|
||||||
// Are you adding more args or attributes here? If they are not reset in _resetStateToDefault, make sure to reset them in FullResetState
|
// Are you adding more args or attributes here? If they are not reset in _resetStateToDefault, make sure to reset them in FullResetState
|
||||||
|
|
||||||
|
|
|
@ -375,6 +375,8 @@ namespace winrt::TerminalApp::implementation
|
||||||
co_return ContentDialogResult::None;
|
co_return ContentDialogResult::None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_dialog = dialog;
|
||||||
|
|
||||||
// IMPORTANT: This is necessary as documented in the ContentDialog MSDN docs.
|
// IMPORTANT: This is necessary as documented in the ContentDialog MSDN docs.
|
||||||
// Since we're hosting the dialog in a Xaml island, we need to connect it to the
|
// Since we're hosting the dialog in a Xaml island, we need to connect it to the
|
||||||
// xaml tree somehow.
|
// xaml tree somehow.
|
||||||
|
@ -412,6 +414,16 @@ namespace winrt::TerminalApp::implementation
|
||||||
// be released so another can be shown
|
// be released so another can be shown
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Method Description:
|
||||||
|
// - Dismiss the (only) visible ContentDialog
|
||||||
|
void AppLogic::DismissDialog()
|
||||||
|
{
|
||||||
|
if (auto localDialog = std::exchange(_dialog, nullptr))
|
||||||
|
{
|
||||||
|
localDialog.Hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
// - Displays a dialog for errors found while loading or validating the
|
// - Displays a dialog for errors found while loading or validating the
|
||||||
// settings. Uses the resources under the provided title and content keys
|
// settings. Uses the resources under the provided title and content keys
|
||||||
|
@ -600,13 +612,11 @@ namespace winrt::TerminalApp::implementation
|
||||||
winrt::Windows::Foundation::Size proposedSize{};
|
winrt::Windows::Foundation::Size proposedSize{};
|
||||||
|
|
||||||
const float scale = static_cast<float>(dpi) / static_cast<float>(USER_DEFAULT_SCREEN_DPI);
|
const float scale = static_cast<float>(dpi) / static_cast<float>(USER_DEFAULT_SCREEN_DPI);
|
||||||
if (_root->ShouldUsePersistedLayout(_settings))
|
if (const auto layout = _root->LoadPersistedLayout(_settings))
|
||||||
{
|
{
|
||||||
const auto layouts = ApplicationState::SharedInstance().PersistedWindowLayouts();
|
if (layout.InitialSize())
|
||||||
|
|
||||||
if (layouts && layouts.Size() > 0 && layouts.GetAt(0).InitialSize())
|
|
||||||
{
|
{
|
||||||
proposedSize = layouts.GetAt(0).InitialSize().Value();
|
proposedSize = layout.InitialSize().Value();
|
||||||
// The size is saved as a non-scaled real pixel size,
|
// The size is saved as a non-scaled real pixel size,
|
||||||
// so we need to scale it appropriately.
|
// so we need to scale it appropriately.
|
||||||
proposedSize.Height = proposedSize.Height * scale;
|
proposedSize.Height = proposedSize.Height * scale;
|
||||||
|
@ -704,13 +714,11 @@ namespace winrt::TerminalApp::implementation
|
||||||
|
|
||||||
auto initialPosition{ _settings.GlobalSettings().InitialPosition() };
|
auto initialPosition{ _settings.GlobalSettings().InitialPosition() };
|
||||||
|
|
||||||
if (_root->ShouldUsePersistedLayout(_settings))
|
if (const auto layout = _root->LoadPersistedLayout(_settings))
|
||||||
{
|
{
|
||||||
const auto layouts = ApplicationState::SharedInstance().PersistedWindowLayouts();
|
if (layout.InitialPosition())
|
||||||
|
|
||||||
if (layouts && layouts.Size() > 0 && layouts.GetAt(0).InitialPosition())
|
|
||||||
{
|
{
|
||||||
initialPosition = layouts.GetAt(0).InitialPosition().Value();
|
initialPosition = layout.InitialPosition().Value();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1151,10 +1159,22 @@ namespace winrt::TerminalApp::implementation
|
||||||
// - <none>
|
// - <none>
|
||||||
// Return Value:
|
// Return Value:
|
||||||
// - <none>
|
// - <none>
|
||||||
void AppLogic::WindowCloseButtonClicked()
|
void AppLogic::CloseWindow(LaunchPosition pos)
|
||||||
{
|
{
|
||||||
if (_root)
|
if (_root)
|
||||||
{
|
{
|
||||||
|
// If persisted layout is enabled and we are the last window closing
|
||||||
|
// we should save our state.
|
||||||
|
if (_root->ShouldUsePersistedLayout(_settings) && _numOpenWindows == 1)
|
||||||
|
{
|
||||||
|
if (const auto layout = _root->GetWindowLayout())
|
||||||
|
{
|
||||||
|
layout.InitialPosition(pos);
|
||||||
|
const auto state = ApplicationState::SharedInstance();
|
||||||
|
state.PersistedWindowLayouts(winrt::single_threaded_vector<WindowLayout>({ layout }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_root->CloseWindow(false);
|
_root->CloseWindow(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1168,6 +1188,16 @@ namespace winrt::TerminalApp::implementation
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AppLogic::HasCommandlineArguments() const noexcept
|
||||||
|
{
|
||||||
|
return _hasCommandLineArguments;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AppLogic::HasSettingsStartupActions() const noexcept
|
||||||
|
{
|
||||||
|
return _hasSettingsStartupActions;
|
||||||
|
}
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
// - Sets the initial commandline to process on startup, and attempts to
|
// - Sets the initial commandline to process on startup, and attempts to
|
||||||
// parse it. Commands will be parsed into a list of ShortcutActions that
|
// parse it. Commands will be parsed into a list of ShortcutActions that
|
||||||
|
@ -1191,6 +1221,10 @@ namespace winrt::TerminalApp::implementation
|
||||||
// then it contains only the executable name and no other arguments.
|
// then it contains only the executable name and no other arguments.
|
||||||
_hasCommandLineArguments = args.size() > 1;
|
_hasCommandLineArguments = args.size() > 1;
|
||||||
_appArgs.ValidateStartupCommands();
|
_appArgs.ValidateStartupCommands();
|
||||||
|
if (const auto idx = _appArgs.GetPersistedLayoutIdx())
|
||||||
|
{
|
||||||
|
_root->SetPersistedLayoutIdx(idx.value());
|
||||||
|
}
|
||||||
_root->SetStartupActions(_appArgs.GetStartupActions());
|
_root->SetStartupActions(_appArgs.GetStartupActions());
|
||||||
|
|
||||||
// Check if we were started as a COM server for inbound connections of console sessions
|
// Check if we were started as a COM server for inbound connections of console sessions
|
||||||
|
@ -1428,6 +1462,40 @@ namespace winrt::TerminalApp::implementation
|
||||||
return _settings.GlobalSettings().ActionMap().GlobalHotkeys();
|
return _settings.GlobalSettings().ActionMap().GlobalHotkeys();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AppLogic::ShouldUsePersistedLayout()
|
||||||
|
{
|
||||||
|
return _root != nullptr ? _root->ShouldUsePersistedLayout(_settings) : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppLogic::SaveWindowLayoutJsons(const Windows::Foundation::Collections::IVector<hstring>& layouts)
|
||||||
|
{
|
||||||
|
std::vector<WindowLayout> converted;
|
||||||
|
converted.reserve(layouts.Size());
|
||||||
|
|
||||||
|
for (const auto& json : layouts)
|
||||||
|
{
|
||||||
|
if (json != L"")
|
||||||
|
{
|
||||||
|
converted.emplace_back(WindowLayout::FromJson(json));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ApplicationState::SharedInstance().PersistedWindowLayouts(winrt::single_threaded_vector(std::move(converted)));
|
||||||
|
}
|
||||||
|
|
||||||
|
hstring AppLogic::GetWindowLayoutJson(LaunchPosition position)
|
||||||
|
{
|
||||||
|
if (_root != nullptr)
|
||||||
|
{
|
||||||
|
if (const auto layout = _root->GetWindowLayout())
|
||||||
|
{
|
||||||
|
layout.InitialPosition(position);
|
||||||
|
return WindowLayout::ToJson(layout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return L"";
|
||||||
|
}
|
||||||
|
|
||||||
void AppLogic::IdentifyWindow()
|
void AppLogic::IdentifyWindow()
|
||||||
{
|
{
|
||||||
if (_root)
|
if (_root)
|
||||||
|
@ -1459,8 +1527,17 @@ namespace winrt::TerminalApp::implementation
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AppLogic::SetPersistedLayoutIdx(const uint32_t idx)
|
||||||
|
{
|
||||||
|
if (_root)
|
||||||
|
{
|
||||||
|
_root->SetPersistedLayoutIdx(idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void AppLogic::SetNumberOfOpenWindows(const uint64_t num)
|
void AppLogic::SetNumberOfOpenWindows(const uint64_t num)
|
||||||
{
|
{
|
||||||
|
_numOpenWindows = num;
|
||||||
if (_root)
|
if (_root)
|
||||||
{
|
{
|
||||||
_root->SetNumberOfOpenWindows(num);
|
_root->SetNumberOfOpenWindows(num);
|
||||||
|
|
|
@ -55,6 +55,8 @@ namespace winrt::TerminalApp::implementation
|
||||||
|
|
||||||
void Quit();
|
void Quit();
|
||||||
|
|
||||||
|
bool HasCommandlineArguments() const noexcept;
|
||||||
|
bool HasSettingsStartupActions() const noexcept;
|
||||||
int32_t SetStartupCommandline(array_view<const winrt::hstring> actions);
|
int32_t SetStartupCommandline(array_view<const winrt::hstring> actions);
|
||||||
int32_t ExecuteCommandline(array_view<const winrt::hstring> actions, const winrt::hstring& cwd);
|
int32_t ExecuteCommandline(array_view<const winrt::hstring> actions, const winrt::hstring& cwd);
|
||||||
TerminalApp::FindTargetWindowResult FindTargetWindow(array_view<const winrt::hstring> actions);
|
TerminalApp::FindTargetWindowResult FindTargetWindow(array_view<const winrt::hstring> actions);
|
||||||
|
@ -65,12 +67,16 @@ namespace winrt::TerminalApp::implementation
|
||||||
bool Fullscreen() const;
|
bool Fullscreen() const;
|
||||||
bool AlwaysOnTop() const;
|
bool AlwaysOnTop() const;
|
||||||
|
|
||||||
|
bool ShouldUsePersistedLayout();
|
||||||
|
hstring GetWindowLayoutJson(Microsoft::Terminal::Settings::Model::LaunchPosition position);
|
||||||
|
void SaveWindowLayoutJsons(const Windows::Foundation::Collections::IVector<hstring>& layouts);
|
||||||
void IdentifyWindow();
|
void IdentifyWindow();
|
||||||
void RenameFailed();
|
void RenameFailed();
|
||||||
winrt::hstring WindowName();
|
winrt::hstring WindowName();
|
||||||
void WindowName(const winrt::hstring& name);
|
void WindowName(const winrt::hstring& name);
|
||||||
uint64_t WindowId();
|
uint64_t WindowId();
|
||||||
void WindowId(const uint64_t& id);
|
void WindowId(const uint64_t& id);
|
||||||
|
void SetPersistedLayoutIdx(const uint32_t idx);
|
||||||
void SetNumberOfOpenWindows(const uint64_t num);
|
void SetNumberOfOpenWindows(const uint64_t num);
|
||||||
bool IsQuakeWindow() const noexcept;
|
bool IsQuakeWindow() const noexcept;
|
||||||
|
|
||||||
|
@ -91,7 +97,7 @@ namespace winrt::TerminalApp::implementation
|
||||||
void TitlebarClicked();
|
void TitlebarClicked();
|
||||||
bool OnDirectKeyEvent(const uint32_t vkey, const uint8_t scanCode, const bool down);
|
bool OnDirectKeyEvent(const uint32_t vkey, const uint8_t scanCode, const bool down);
|
||||||
|
|
||||||
void WindowCloseButtonClicked();
|
void CloseWindow(Microsoft::Terminal::Settings::Model::LaunchPosition position);
|
||||||
|
|
||||||
winrt::TerminalApp::TaskbarState TaskbarState();
|
winrt::TerminalApp::TaskbarState TaskbarState();
|
||||||
|
|
||||||
|
@ -100,6 +106,7 @@ namespace winrt::TerminalApp::implementation
|
||||||
bool GetShowTitleInTitlebar();
|
bool GetShowTitleInTitlebar();
|
||||||
|
|
||||||
winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::UI::Xaml::Controls::ContentDialogResult> ShowDialog(winrt::Windows::UI::Xaml::Controls::ContentDialog dialog);
|
winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::UI::Xaml::Controls::ContentDialogResult> ShowDialog(winrt::Windows::UI::Xaml::Controls::ContentDialog dialog);
|
||||||
|
void DismissDialog();
|
||||||
|
|
||||||
Windows::Foundation::Collections::IMapView<Microsoft::Terminal::Control::KeyChord, Microsoft::Terminal::Settings::Model::Command> GlobalHotkeys();
|
Windows::Foundation::Collections::IMapView<Microsoft::Terminal::Control::KeyChord, Microsoft::Terminal::Settings::Model::Command> GlobalHotkeys();
|
||||||
|
|
||||||
|
@ -123,7 +130,10 @@ namespace winrt::TerminalApp::implementation
|
||||||
HRESULT _settingsLoadedResult = S_OK;
|
HRESULT _settingsLoadedResult = S_OK;
|
||||||
bool _loadedInitialSettings = false;
|
bool _loadedInitialSettings = false;
|
||||||
|
|
||||||
|
uint64_t _numOpenWindows{ 0 };
|
||||||
|
|
||||||
std::shared_mutex _dialogLock;
|
std::shared_mutex _dialogLock;
|
||||||
|
winrt::Windows::UI::Xaml::Controls::ContentDialog _dialog;
|
||||||
|
|
||||||
::TerminalApp::AppCommandlineArgs _appArgs;
|
::TerminalApp::AppCommandlineArgs _appArgs;
|
||||||
::TerminalApp::AppCommandlineArgs _settingsAppArgs;
|
::TerminalApp::AppCommandlineArgs _settingsAppArgs;
|
||||||
|
@ -175,6 +185,7 @@ namespace winrt::TerminalApp::implementation
|
||||||
FORWARDED_TYPED_EVENT(RenameWindowRequested, Windows::Foundation::IInspectable, winrt::TerminalApp::RenameWindowRequestedArgs, _root, RenameWindowRequested);
|
FORWARDED_TYPED_EVENT(RenameWindowRequested, Windows::Foundation::IInspectable, winrt::TerminalApp::RenameWindowRequestedArgs, _root, RenameWindowRequested);
|
||||||
FORWARDED_TYPED_EVENT(IsQuakeWindowChanged, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, IsQuakeWindowChanged);
|
FORWARDED_TYPED_EVENT(IsQuakeWindowChanged, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, IsQuakeWindowChanged);
|
||||||
FORWARDED_TYPED_EVENT(SummonWindowRequested, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, SummonWindowRequested);
|
FORWARDED_TYPED_EVENT(SummonWindowRequested, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, SummonWindowRequested);
|
||||||
|
FORWARDED_TYPED_EVENT(CloseRequested, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, CloseRequested);
|
||||||
FORWARDED_TYPED_EVENT(OpenSystemMenu, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, OpenSystemMenu);
|
FORWARDED_TYPED_EVENT(OpenSystemMenu, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, OpenSystemMenu);
|
||||||
FORWARDED_TYPED_EVENT(QuitRequested, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, QuitRequested);
|
FORWARDED_TYPED_EVENT(QuitRequested, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, QuitRequested);
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,8 @@ namespace TerminalApp
|
||||||
void RunAsUwp();
|
void RunAsUwp();
|
||||||
Boolean IsElevated();
|
Boolean IsElevated();
|
||||||
|
|
||||||
|
Boolean HasCommandlineArguments();
|
||||||
|
Boolean HasSettingsStartupActions();
|
||||||
Int32 SetStartupCommandline(String[] commands);
|
Int32 SetStartupCommandline(String[] commands);
|
||||||
Int32 ExecuteCommandline(String[] commands, String cwd);
|
Int32 ExecuteCommandline(String[] commands, String cwd);
|
||||||
String ParseCommandlineMessage { get; };
|
String ParseCommandlineMessage { get; };
|
||||||
|
@ -55,6 +57,7 @@ namespace TerminalApp
|
||||||
void IdentifyWindow();
|
void IdentifyWindow();
|
||||||
String WindowName;
|
String WindowName;
|
||||||
UInt64 WindowId;
|
UInt64 WindowId;
|
||||||
|
void SetPersistedLayoutIdx(UInt32 idx);
|
||||||
void SetNumberOfOpenWindows(UInt64 num);
|
void SetNumberOfOpenWindows(UInt64 num);
|
||||||
void RenameFailed();
|
void RenameFailed();
|
||||||
Boolean IsQuakeWindow();
|
Boolean IsQuakeWindow();
|
||||||
|
@ -69,10 +72,14 @@ namespace TerminalApp
|
||||||
Boolean GetInitialAlwaysOnTop();
|
Boolean GetInitialAlwaysOnTop();
|
||||||
Single CalcSnappedDimension(Boolean widthOrHeight, Single dimension);
|
Single CalcSnappedDimension(Boolean widthOrHeight, Single dimension);
|
||||||
void TitlebarClicked();
|
void TitlebarClicked();
|
||||||
void WindowCloseButtonClicked();
|
void CloseWindow(Microsoft.Terminal.Settings.Model.LaunchPosition position);
|
||||||
|
|
||||||
TaskbarState TaskbarState{ get; };
|
TaskbarState TaskbarState{ get; };
|
||||||
|
|
||||||
|
Boolean ShouldUsePersistedLayout();
|
||||||
|
String GetWindowLayoutJson(Microsoft.Terminal.Settings.Model.LaunchPosition position);
|
||||||
|
void SaveWindowLayoutJsons(Windows.Foundation.Collections.IVector<String> layouts);
|
||||||
|
|
||||||
Boolean GetMinimizeToNotificationArea();
|
Boolean GetMinimizeToNotificationArea();
|
||||||
Boolean GetAlwaysShowNotificationIcon();
|
Boolean GetAlwaysShowNotificationIcon();
|
||||||
Boolean GetShowTitleInTitlebar();
|
Boolean GetShowTitleInTitlebar();
|
||||||
|
@ -84,6 +91,7 @@ namespace TerminalApp
|
||||||
// See IDialogPresenter and TerminalPage's DialogPresenter for more
|
// See IDialogPresenter and TerminalPage's DialogPresenter for more
|
||||||
// information.
|
// information.
|
||||||
Windows.Foundation.IAsyncOperation<Windows.UI.Xaml.Controls.ContentDialogResult> ShowDialog(Windows.UI.Xaml.Controls.ContentDialog dialog);
|
Windows.Foundation.IAsyncOperation<Windows.UI.Xaml.Controls.ContentDialogResult> ShowDialog(Windows.UI.Xaml.Controls.ContentDialog dialog);
|
||||||
|
void DismissDialog();
|
||||||
|
|
||||||
event Windows.Foundation.TypedEventHandler<Object, Windows.UI.Xaml.UIElement> SetTitleBarContent;
|
event Windows.Foundation.TypedEventHandler<Object, Windows.UI.Xaml.UIElement> SetTitleBarContent;
|
||||||
event Windows.Foundation.TypedEventHandler<Object, String> TitleChanged;
|
event Windows.Foundation.TypedEventHandler<Object, String> TitleChanged;
|
||||||
|
@ -99,6 +107,7 @@ namespace TerminalApp
|
||||||
event Windows.Foundation.TypedEventHandler<Object, Object> SettingsChanged;
|
event Windows.Foundation.TypedEventHandler<Object, Object> SettingsChanged;
|
||||||
event Windows.Foundation.TypedEventHandler<Object, Object> IsQuakeWindowChanged;
|
event Windows.Foundation.TypedEventHandler<Object, Object> IsQuakeWindowChanged;
|
||||||
event Windows.Foundation.TypedEventHandler<Object, Object> SummonWindowRequested;
|
event Windows.Foundation.TypedEventHandler<Object, Object> SummonWindowRequested;
|
||||||
|
event Windows.Foundation.TypedEventHandler<Object, Object> CloseRequested;
|
||||||
event Windows.Foundation.TypedEventHandler<Object, Object> OpenSystemMenu;
|
event Windows.Foundation.TypedEventHandler<Object, Object> OpenSystemMenu;
|
||||||
event Windows.Foundation.TypedEventHandler<Object, Object> QuitRequested;
|
event Windows.Foundation.TypedEventHandler<Object, Object> QuitRequested;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,8 +21,22 @@ namespace winrt::Microsoft::TerminalApp::implementation
|
||||||
}
|
}
|
||||||
void Initialize(const Windows::Foundation::Collections::ValueSet& /*settings*/) {}
|
void Initialize(const Windows::Foundation::Collections::ValueSet& /*settings*/) {}
|
||||||
~DebugInputTapConnection() = default;
|
~DebugInputTapConnection() = default;
|
||||||
void Start()
|
winrt::fire_and_forget Start()
|
||||||
{
|
{
|
||||||
|
// GH#11282: It's possible that we're about to be started, _before_
|
||||||
|
// our paired connection is started. Both will get Start()'ed when
|
||||||
|
// their owning TermControl is finally laid out. However, if we're
|
||||||
|
// started first, then we'll immediately start printing to the other
|
||||||
|
// control as well, which might not have initialized yet. If we do
|
||||||
|
// that, we'll explode.
|
||||||
|
//
|
||||||
|
// Instead, wait here until the other connection is started too,
|
||||||
|
// before actually starting the connection to the client app. This
|
||||||
|
// will ensure both controls are initialized before the client app
|
||||||
|
// is.
|
||||||
|
co_await winrt::resume_background();
|
||||||
|
_pairedTap->_start.wait();
|
||||||
|
|
||||||
_wrappedConnection.Start();
|
_wrappedConnection.Start();
|
||||||
}
|
}
|
||||||
void WriteInput(hstring const& data)
|
void WriteInput(hstring const& data)
|
||||||
|
@ -59,6 +73,9 @@ namespace winrt::Microsoft::TerminalApp::implementation
|
||||||
void DebugTapConnection::Start()
|
void DebugTapConnection::Start()
|
||||||
{
|
{
|
||||||
// presume the wrapped connection is started.
|
// presume the wrapped connection is started.
|
||||||
|
|
||||||
|
// This is explained in the comment for GH#11282 above.
|
||||||
|
_start.count_down();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugTapConnection::WriteInput(hstring const& data)
|
void DebugTapConnection::WriteInput(hstring const& data)
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
#include <winrt/Microsoft.Terminal.TerminalConnection.h>
|
#include <winrt/Microsoft.Terminal.TerminalConnection.h>
|
||||||
#include "../../inc/cppwinrt_utils.h"
|
#include "../../inc/cppwinrt_utils.h"
|
||||||
|
#include <til/latch.h>
|
||||||
|
|
||||||
namespace winrt::Microsoft::TerminalApp::implementation
|
namespace winrt::Microsoft::TerminalApp::implementation
|
||||||
{
|
{
|
||||||
|
@ -36,6 +37,8 @@ namespace winrt::Microsoft::TerminalApp::implementation
|
||||||
winrt::weak_ref<Microsoft::Terminal::TerminalConnection::ITerminalConnection> _wrappedConnection;
|
winrt::weak_ref<Microsoft::Terminal::TerminalConnection::ITerminalConnection> _wrappedConnection;
|
||||||
winrt::weak_ref<Microsoft::Terminal::TerminalConnection::ITerminalConnection> _inputSide;
|
winrt::weak_ref<Microsoft::Terminal::TerminalConnection::ITerminalConnection> _inputSide;
|
||||||
|
|
||||||
|
til::latch _start{ 1 };
|
||||||
|
|
||||||
friend class DebugInputTapConnection;
|
friend class DebugInputTapConnection;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -40,7 +40,8 @@ enum class Borders : int
|
||||||
Top = 0x1,
|
Top = 0x1,
|
||||||
Bottom = 0x2,
|
Bottom = 0x2,
|
||||||
Left = 0x4,
|
Left = 0x4,
|
||||||
Right = 0x8
|
Right = 0x8,
|
||||||
|
All = 0xF
|
||||||
};
|
};
|
||||||
DEFINE_ENUM_FLAG_OPERATORS(Borders);
|
DEFINE_ENUM_FLAG_OPERATORS(Borders);
|
||||||
|
|
||||||
|
@ -58,7 +59,14 @@ public:
|
||||||
const winrt::Microsoft::Terminal::Control::TermControl& control,
|
const winrt::Microsoft::Terminal::Control::TermControl& control,
|
||||||
const bool lastFocused = false);
|
const bool lastFocused = false);
|
||||||
|
|
||||||
|
Pane(std::shared_ptr<Pane> first,
|
||||||
|
std::shared_ptr<Pane> second,
|
||||||
|
const SplitState splitType,
|
||||||
|
const float splitPosition,
|
||||||
|
const bool lastFocused = false);
|
||||||
|
|
||||||
std::shared_ptr<Pane> GetActivePane();
|
std::shared_ptr<Pane> GetActivePane();
|
||||||
|
winrt::Microsoft::Terminal::Control::TermControl GetLastFocusedTerminalControl();
|
||||||
winrt::Microsoft::Terminal::Control::TermControl GetTerminalControl();
|
winrt::Microsoft::Terminal::Control::TermControl GetTerminalControl();
|
||||||
winrt::Microsoft::Terminal::Settings::Model::Profile GetFocusedProfile();
|
winrt::Microsoft::Terminal::Settings::Model::Profile GetFocusedProfile();
|
||||||
|
|
||||||
|
@ -142,25 +150,43 @@ public:
|
||||||
// - true if the predicate returned true on any pane.
|
// - true if the predicate returned true on any pane.
|
||||||
template<typename F>
|
template<typename F>
|
||||||
//requires std::predicate<F, std::shared_ptr<Pane>>
|
//requires std::predicate<F, std::shared_ptr<Pane>>
|
||||||
bool WalkTree(F f)
|
auto WalkTree(F f) -> decltype(f(shared_from_this()))
|
||||||
{
|
{
|
||||||
if (f(shared_from_this()))
|
using R = std::invoke_result_t<F, std::shared_ptr<Pane>>;
|
||||||
{
|
static constexpr auto IsVoid = std::is_void_v<R>;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_IsLeaf())
|
if constexpr (IsVoid)
|
||||||
{
|
{
|
||||||
return _firstChild->WalkTree(f) || _secondChild->WalkTree(f);
|
f(shared_from_this());
|
||||||
|
if (!_IsLeaf())
|
||||||
|
{
|
||||||
|
_firstChild->WalkTree(f);
|
||||||
|
_secondChild->WalkTree(f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (f(shared_from_this()))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
if (!_IsLeaf())
|
||||||
|
{
|
||||||
|
return _firstChild->WalkTree(f) || _secondChild->WalkTree(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CollectTaskbarStates(std::vector<winrt::TerminalApp::TaskbarState>& states);
|
void CollectTaskbarStates(std::vector<winrt::TerminalApp::TaskbarState>& states);
|
||||||
|
|
||||||
WINRT_CALLBACK(Closed, winrt::Windows::Foundation::EventHandler<winrt::Windows::Foundation::IInspectable>);
|
WINRT_CALLBACK(Closed, winrt::Windows::Foundation::EventHandler<winrt::Windows::Foundation::IInspectable>);
|
||||||
DECLARE_EVENT(GotFocus, _GotFocusHandlers, winrt::delegate<std::shared_ptr<Pane>>);
|
|
||||||
|
using gotFocusArgs = winrt::delegate<std::shared_ptr<Pane>, winrt::Windows::UI::Xaml::FocusState>;
|
||||||
|
|
||||||
|
DECLARE_EVENT(GotFocus, _GotFocusHandlers, gotFocusArgs);
|
||||||
DECLARE_EVENT(LostFocus, _LostFocusHandlers, 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>);
|
DECLARE_EVENT(PaneRaiseBell, _PaneRaiseBellHandlers, winrt::Windows::Foundation::EventHandler<bool>);
|
||||||
DECLARE_EVENT(Detached, _PaneDetachedHandlers, winrt::delegate<std::shared_ptr<Pane>>);
|
DECLARE_EVENT(Detached, _PaneDetachedHandlers, winrt::delegate<std::shared_ptr<Pane>>);
|
||||||
|
@ -173,7 +199,8 @@ private:
|
||||||
struct LayoutSizeNode;
|
struct LayoutSizeNode;
|
||||||
|
|
||||||
winrt::Windows::UI::Xaml::Controls::Grid _root{};
|
winrt::Windows::UI::Xaml::Controls::Grid _root{};
|
||||||
winrt::Windows::UI::Xaml::Controls::Border _border{};
|
winrt::Windows::UI::Xaml::Controls::Border _borderFirst{};
|
||||||
|
winrt::Windows::UI::Xaml::Controls::Border _borderSecond{};
|
||||||
winrt::Microsoft::Terminal::Control::TermControl _control{ nullptr };
|
winrt::Microsoft::Terminal::Control::TermControl _control{ nullptr };
|
||||||
winrt::Microsoft::Terminal::TerminalConnection::ConnectionState _connectionState{ winrt::Microsoft::Terminal::TerminalConnection::ConnectionState::NotConnected };
|
winrt::Microsoft::Terminal::TerminalConnection::ConnectionState _connectionState{ winrt::Microsoft::Terminal::TerminalConnection::ConnectionState::NotConnected };
|
||||||
static winrt::Windows::UI::Xaml::Media::SolidColorBrush s_focusedBorderBrush;
|
static winrt::Windows::UI::Xaml::Media::SolidColorBrush s_focusedBorderBrush;
|
||||||
|
@ -185,6 +212,7 @@ private:
|
||||||
float _desiredSplitPosition;
|
float _desiredSplitPosition;
|
||||||
|
|
||||||
std::optional<uint32_t> _id;
|
std::optional<uint32_t> _id;
|
||||||
|
std::weak_ptr<Pane> _parentChildPath{};
|
||||||
|
|
||||||
bool _lastActive{ false };
|
bool _lastActive{ false };
|
||||||
winrt::Microsoft::Terminal::Settings::Model::Profile _profile{ nullptr };
|
winrt::Microsoft::Terminal::Settings::Model::Profile _profile{ nullptr };
|
||||||
|
@ -205,6 +233,7 @@ private:
|
||||||
bool _IsLeaf() const noexcept;
|
bool _IsLeaf() const noexcept;
|
||||||
bool _HasFocusedChild() const noexcept;
|
bool _HasFocusedChild() const noexcept;
|
||||||
void _SetupChildCloseHandlers();
|
void _SetupChildCloseHandlers();
|
||||||
|
bool _HasChild(const std::shared_ptr<Pane> child);
|
||||||
|
|
||||||
std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> _Split(winrt::Microsoft::Terminal::Settings::Model::SplitDirection splitType,
|
std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> _Split(winrt::Microsoft::Terminal::Settings::Model::SplitDirection splitType,
|
||||||
const float splitSize,
|
const float splitSize,
|
||||||
|
@ -232,6 +261,7 @@ private:
|
||||||
void _CloseChild(const bool closeFirst, const bool isDetaching);
|
void _CloseChild(const bool closeFirst, const bool isDetaching);
|
||||||
winrt::fire_and_forget _CloseChildRoutine(const bool closeFirst);
|
winrt::fire_and_forget _CloseChildRoutine(const bool closeFirst);
|
||||||
|
|
||||||
|
void _Focus();
|
||||||
void _FocusFirstChild();
|
void _FocusFirstChild();
|
||||||
void _ControlConnectionStateChangedHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& /*args*/);
|
void _ControlConnectionStateChangedHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& /*args*/);
|
||||||
void _ControlWarningBellHandler(winrt::Windows::Foundation::IInspectable const& sender,
|
void _ControlWarningBellHandler(winrt::Windows::Foundation::IInspectable const& sender,
|
||||||
|
|
|
@ -190,6 +190,9 @@
|
||||||
<data name="CloseWindowWarningTitle" xml:space="preserve">
|
<data name="CloseWindowWarningTitle" xml:space="preserve">
|
||||||
<value>Do you want to close all tabs?</value>
|
<value>Do you want to close all tabs?</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="MultiplePanes" xml:space="preserve">
|
||||||
|
<value>Multiple panes</value>
|
||||||
|
</data>
|
||||||
<data name="TabCloseSubMenu" xml:space="preserve">
|
<data name="TabCloseSubMenu" xml:space="preserve">
|
||||||
<value>Close...</value>
|
<value>Close...</value>
|
||||||
</data>
|
</data>
|
||||||
|
@ -381,6 +384,9 @@
|
||||||
<data name="CmdFocusDesc" xml:space="preserve">
|
<data name="CmdFocusDesc" xml:space="preserve">
|
||||||
<value>Launch the window in focus mode</value>
|
<value>Launch the window in focus mode</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="CmdSavedLayoutArgDesc" xml:space="preserve">
|
||||||
|
<value>This parameter is an internal implementation detail and should not be used.</value>
|
||||||
|
</data>
|
||||||
<data name="CmdWindowTargetArgDesc" xml:space="preserve">
|
<data name="CmdWindowTargetArgDesc" xml:space="preserve">
|
||||||
<value>Specify a terminal window to run the given commandline in. "0" always refers to the current window. </value>
|
<value>Specify a terminal window to run the given commandline in. "0" always refers to the current window. </value>
|
||||||
</data>
|
</data>
|
||||||
|
@ -712,10 +718,17 @@
|
||||||
<data name="CloseOnExitInfoBar.Message" xml:space="preserve">
|
<data name="CloseOnExitInfoBar.Message" xml:space="preserve">
|
||||||
<value>Termination behavior can be configured in advanced profile settings.</value>
|
<value>Termination behavior can be configured in advanced profile settings.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SetAsDefaultInfoBar.Message" xml:space="preserve">
|
||||||
|
<value>Windows Terminal can be set as the default terminal application in your settings.</value>
|
||||||
|
</data>
|
||||||
<data name="InfoBarDismissButton.Content" xml:space="preserve">
|
<data name="InfoBarDismissButton.Content" xml:space="preserve">
|
||||||
<value>Don't show again</value>
|
<value>Don't show again</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ElevationShield.[using:Windows.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
|
<data name="ElevationShield.[using:Windows.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
|
||||||
<value>This Terminal window is running as Admin</value>
|
<value>This Terminal window is running as Admin</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SetAsDefaultTip_OpenSettingsLink.Content" xml:space="preserve">
|
||||||
|
<value>Open Settings</value>
|
||||||
|
<comment>This is a call-to-action hyperlink; it will open the settings.</comment>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
|
@ -19,6 +19,9 @@
|
||||||
#include "ColorHelper.h"
|
#include "ColorHelper.h"
|
||||||
#include "DebugTapConnection.h"
|
#include "DebugTapConnection.h"
|
||||||
#include "SettingsTab.h"
|
#include "SettingsTab.h"
|
||||||
|
#include "..\TerminalSettingsModel\FileUtils.h"
|
||||||
|
|
||||||
|
#include <shlobj.h>
|
||||||
|
|
||||||
using namespace winrt;
|
using namespace winrt;
|
||||||
using namespace winrt::Windows::Foundation::Collections;
|
using namespace winrt::Windows::Foundation::Collections;
|
||||||
|
@ -410,33 +413,45 @@ namespace winrt::TerminalApp::implementation
|
||||||
// - tab: tab to export
|
// - tab: tab to export
|
||||||
winrt::fire_and_forget TerminalPage::_ExportTab(const TerminalTab& tab)
|
winrt::fire_and_forget TerminalPage::_ExportTab(const TerminalTab& tab)
|
||||||
{
|
{
|
||||||
|
// This will be used to set up the file picker "filter", to select .txt
|
||||||
|
// files by default.
|
||||||
|
static constexpr COMDLG_FILTERSPEC supportedFileTypes[] = {
|
||||||
|
{ L"Text Files (*.txt)", L"*.txt" },
|
||||||
|
{ L"All Files (*.*)", L"*.*" }
|
||||||
|
};
|
||||||
|
// An arbitrary GUID to associate with all instances of this
|
||||||
|
// dialog, so they all re-open in the same path as they were
|
||||||
|
// open before:
|
||||||
|
static constexpr winrt::guid clientGuidExportFile{ 0xF6AF20BB, 0x0800, 0x48E6, { 0xB0, 0x17, 0xA1, 0x4C, 0xD8, 0x73, 0xDD, 0x58 } };
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (const auto control{ tab.GetActiveTerminalControl() })
|
if (const auto control{ tab.GetActiveTerminalControl() })
|
||||||
{
|
{
|
||||||
const FileSavePicker savePicker;
|
// GH#11356 - we can't use the UWP apis for writing the file,
|
||||||
savePicker.as<IInitializeWithWindow>()->Initialize(*_hostingHwnd);
|
// because they don't work elevated (shocker) So just use the
|
||||||
savePicker.SuggestedStartLocation(PickerLocationId::Downloads);
|
// shell32 file picker manually.
|
||||||
const auto fileChoices = single_threaded_vector<hstring>({ L".txt" });
|
auto path = co_await SaveFilePicker(*_hostingHwnd, [control](auto&& dialog) {
|
||||||
savePicker.FileTypeChoices().Insert(RS_(L"PlainText"), fileChoices);
|
THROW_IF_FAILED(dialog->SetClientGuid(clientGuidExportFile));
|
||||||
savePicker.SuggestedFileName(control.Title());
|
try
|
||||||
|
{
|
||||||
|
// Default to the Downloads folder
|
||||||
|
auto folderShellItem{ winrt::capture<IShellItem>(&SHGetKnownFolderItem, FOLDERID_Downloads, KF_FLAG_DEFAULT, nullptr) };
|
||||||
|
dialog->SetDefaultFolder(folderShellItem.get());
|
||||||
|
}
|
||||||
|
CATCH_LOG(); // non-fatal
|
||||||
|
THROW_IF_FAILED(dialog->SetFileTypes(ARRAYSIZE(supportedFileTypes), supportedFileTypes));
|
||||||
|
THROW_IF_FAILED(dialog->SetFileTypeIndex(1)); // the array is 1-indexed
|
||||||
|
THROW_IF_FAILED(dialog->SetDefaultExtension(L"txt"));
|
||||||
|
|
||||||
const StorageFile file = co_await savePicker.PickSaveFileAsync();
|
// Default to using the tab title as the file name
|
||||||
if (file != nullptr)
|
THROW_IF_FAILED(dialog->SetFileName((control.Title() + L".txt").c_str()));
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!path.empty())
|
||||||
{
|
{
|
||||||
const auto buffer = control.ReadEntireBuffer();
|
const auto buffer = control.ReadEntireBuffer();
|
||||||
CachedFileManager::DeferUpdates(file);
|
CascadiaSettings::ExportFile(path, buffer);
|
||||||
co_await FileIO::WriteTextAsync(file, buffer);
|
|
||||||
const auto status = co_await CachedFileManager::CompleteUpdatesAsync(file);
|
|
||||||
switch (status)
|
|
||||||
{
|
|
||||||
case FileUpdateStatus::Complete:
|
|
||||||
case FileUpdateStatus::CompleteAndRenamed:
|
|
||||||
_ShowControlNoticeDialog(RS_(L"NoticeInfo"), RS_(L"ExportSuccess"));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
_ShowControlNoticeDialog(RS_(L"NoticeError"), RS_(L"ExportFailure"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -501,7 +516,9 @@ namespace winrt::TerminalApp::implementation
|
||||||
{
|
{
|
||||||
// If we are supposed to save state, make sure we clear it out
|
// If we are supposed to save state, make sure we clear it out
|
||||||
// if the user manually closed all tabs.
|
// if the user manually closed all tabs.
|
||||||
if (!_maintainStateOnTabClose && ShouldUsePersistedLayout(_settings))
|
// Do this only if we are the last window; the monarch will notice
|
||||||
|
// we are missing and remove us that way otherwise.
|
||||||
|
if (!_maintainStateOnTabClose && ShouldUsePersistedLayout(_settings) && _numOpenWindows == 1)
|
||||||
{
|
{
|
||||||
auto state = ApplicationState::SharedInstance();
|
auto state = ApplicationState::SharedInstance();
|
||||||
state.PersistedWindowLayouts(nullptr);
|
state.PersistedWindowLayouts(nullptr);
|
||||||
|
@ -734,31 +751,32 @@ namespace winrt::TerminalApp::implementation
|
||||||
{
|
{
|
||||||
_UnZoomIfNeeded();
|
_UnZoomIfNeeded();
|
||||||
|
|
||||||
auto pane = terminalTab->GetActivePane();
|
|
||||||
|
|
||||||
if (const auto pane{ terminalTab->GetActivePane() })
|
if (const auto pane{ terminalTab->GetActivePane() })
|
||||||
{
|
{
|
||||||
if (const auto control{ pane->GetTerminalControl() })
|
if (pane->ContainsReadOnly())
|
||||||
{
|
{
|
||||||
if (control.ReadOnly())
|
ContentDialogResult warningResult = co_await _ShowCloseReadOnlyDialog();
|
||||||
|
|
||||||
|
// If the user didn't explicitly click on close tab - leave
|
||||||
|
if (warningResult != ContentDialogResult::Primary)
|
||||||
{
|
{
|
||||||
ContentDialogResult warningResult = co_await _ShowCloseReadOnlyDialog();
|
co_return;
|
||||||
|
|
||||||
// If the user didn't explicitly click on close tab - leave
|
|
||||||
if (warningResult != ContentDialogResult::Primary)
|
|
||||||
{
|
|
||||||
co_return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clean read-only mode to prevent additional prompt if closing the pane triggers closing of a hosting tab
|
|
||||||
if (control.ReadOnly())
|
|
||||||
{
|
|
||||||
control.ToggleReadOnly();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pane->Close();
|
// Clean read-only mode to prevent additional prompt if closing the pane triggers closing of a hosting tab
|
||||||
|
pane->WalkTree([](auto p) {
|
||||||
|
if (const auto control{ p->GetTerminalControl() })
|
||||||
|
{
|
||||||
|
if (control.ReadOnly())
|
||||||
|
{
|
||||||
|
control.ToggleReadOnly();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pane->Close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (auto index{ _GetFocusedTabIndex() })
|
else if (auto index{ _GetFocusedTabIndex() })
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
<mux:TabView.TabStripHeader>
|
<mux:TabView.TabStripHeader>
|
||||||
<!-- EA18 is the "Shield" glyph -->
|
<!-- EA18 is the "Shield" glyph -->
|
||||||
<FontIcon x:Uid="ElevationShield"
|
<FontIcon x:Uid="ElevationShield"
|
||||||
Margin="9,4,0,0"
|
Margin="9,4,0,4"
|
||||||
FontFamily="Segoe MDL2 Assets"
|
FontFamily="Segoe MDL2 Assets"
|
||||||
FontSize="16"
|
FontSize="16"
|
||||||
Foreground="{ThemeResource SystemControlForegroundBaseMediumBrush}"
|
Foreground="{ThemeResource SystemControlForegroundBaseMediumBrush}"
|
||||||
|
|
|
@ -218,7 +218,7 @@ namespace winrt::TerminalApp::implementation
|
||||||
_RegisterActionCallbacks();
|
_RegisterActionCallbacks();
|
||||||
|
|
||||||
// Hook up inbound connection event handler
|
// Hook up inbound connection event handler
|
||||||
TerminalConnection::ConptyConnection::NewConnection({ this, &TerminalPage::_OnNewConnection });
|
ConptyConnection::NewConnection({ this, &TerminalPage::_OnNewConnection });
|
||||||
|
|
||||||
//Event Bindings (Early)
|
//Event Bindings (Early)
|
||||||
_newTabButton.Click([weakThis{ get_weak() }](auto&&, auto&&) {
|
_newTabButton.Click([weakThis{ get_weak() }](auto&&, auto&&) {
|
||||||
|
@ -287,6 +287,8 @@ namespace winrt::TerminalApp::implementation
|
||||||
_defaultPointerCursor = CoreWindow::GetForCurrentThread().PointerCursor();
|
_defaultPointerCursor = CoreWindow::GetForCurrentThread().PointerCursor();
|
||||||
}
|
}
|
||||||
CATCH_LOG();
|
CATCH_LOG();
|
||||||
|
|
||||||
|
ShowSetAsDefaultInfoBar();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method Description;
|
// Method Description;
|
||||||
|
@ -298,10 +300,37 @@ namespace winrt::TerminalApp::implementation
|
||||||
// - true if the ApplicationState should be used.
|
// - true if the ApplicationState should be used.
|
||||||
bool TerminalPage::ShouldUsePersistedLayout(CascadiaSettings& settings) const
|
bool TerminalPage::ShouldUsePersistedLayout(CascadiaSettings& settings) const
|
||||||
{
|
{
|
||||||
// If the setting is enabled, and we are the only window.
|
// GH#5000 Until there is a separate state file for elevated sessions we should just not
|
||||||
|
// save at all while in an elevated window.
|
||||||
return Feature_PersistedWindowLayout::IsEnabled() &&
|
return Feature_PersistedWindowLayout::IsEnabled() &&
|
||||||
settings.GlobalSettings().FirstWindowPreference() == FirstWindowPreference::PersistedWindowLayout &&
|
!IsElevated() &&
|
||||||
_numOpenWindows == 1;
|
settings.GlobalSettings().FirstWindowPreference() == FirstWindowPreference::PersistedWindowLayout;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method Description;
|
||||||
|
// - Checks if the current window is configured to load a particular layout
|
||||||
|
// Arguments:
|
||||||
|
// - settings: The settings to use as this may be called before the page is
|
||||||
|
// fully initialized.
|
||||||
|
// Return Value:
|
||||||
|
// - non-null if there is a particular saved layout to use
|
||||||
|
std::optional<uint32_t> TerminalPage::LoadPersistedLayoutIdx(CascadiaSettings& settings) const
|
||||||
|
{
|
||||||
|
return ShouldUsePersistedLayout(settings) ? _loadFromPersistedLayoutIdx : std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
WindowLayout TerminalPage::LoadPersistedLayout(CascadiaSettings& settings) const
|
||||||
|
{
|
||||||
|
if (const auto idx = LoadPersistedLayoutIdx(settings))
|
||||||
|
{
|
||||||
|
const auto i = idx.value();
|
||||||
|
const auto layouts = ApplicationState::SharedInstance().PersistedWindowLayouts();
|
||||||
|
if (layouts && layouts.Size() > i)
|
||||||
|
{
|
||||||
|
return layouts.GetAt(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
winrt::fire_and_forget TerminalPage::NewTerminalByDrop(winrt::Windows::UI::Xaml::DragEventArgs& e)
|
winrt::fire_and_forget TerminalPage::NewTerminalByDrop(winrt::Windows::UI::Xaml::DragEventArgs& e)
|
||||||
|
@ -387,30 +416,13 @@ namespace winrt::TerminalApp::implementation
|
||||||
{
|
{
|
||||||
_startupState = StartupState::InStartup;
|
_startupState = StartupState::InStartup;
|
||||||
|
|
||||||
// If the user selected to save their tab layout, we are the first
|
// If we are provided with an index, the cases where we have
|
||||||
// window opened, and wt was not run with any other arguments, then
|
// commandline args and startup actions are already handled.
|
||||||
// we should use the saved settings.
|
if (const auto layout = LoadPersistedLayout(_settings))
|
||||||
auto firstActionIsDefault = [](ActionAndArgs action) {
|
|
||||||
if (action.Action() != ShortcutAction::NewTab)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If no commands were given, we will have default args
|
|
||||||
if (const auto args = action.Args().try_as<NewTabArgs>())
|
|
||||||
{
|
|
||||||
NewTerminalArgs defaultArgs{};
|
|
||||||
return args.TerminalArgs() == nullptr || args.TerminalArgs().Equals(defaultArgs);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
if (ShouldUsePersistedLayout(_settings) && _startupActions.Size() == 1 && firstActionIsDefault(_startupActions.GetAt(0)))
|
|
||||||
{
|
{
|
||||||
auto layouts = ApplicationState::SharedInstance().PersistedWindowLayouts();
|
if (layout.TabLayout().Size() > 0)
|
||||||
if (layouts && layouts.Size() > 0 && layouts.GetAt(0).TabLayout() && layouts.GetAt(0).TabLayout().Size() > 0)
|
|
||||||
{
|
{
|
||||||
_startupActions = layouts.GetAt(0).TabLayout();
|
_startupActions = layout.TabLayout();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1289,12 +1301,19 @@ namespace winrt::TerminalApp::implementation
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
// - Saves the window position and tab layout to the application state
|
// - Saves the window position and tab layout to the application state
|
||||||
|
// - This does not create the InitialPosition field, that needs to be
|
||||||
|
// added externally.
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// - <none>
|
// - <none>
|
||||||
// Return Value:
|
// Return Value:
|
||||||
// - <none>
|
// - the window layout
|
||||||
void TerminalPage::PersistWindowLayout()
|
WindowLayout TerminalPage::GetWindowLayout()
|
||||||
{
|
{
|
||||||
|
if (_startupState != StartupState::Initialized)
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<ActionAndArgs> actions;
|
std::vector<ActionAndArgs> actions;
|
||||||
|
|
||||||
for (auto tab : _tabs)
|
for (auto tab : _tabs)
|
||||||
|
@ -1302,7 +1321,7 @@ namespace winrt::TerminalApp::implementation
|
||||||
if (auto terminalTab = _GetTerminalTabImpl(tab))
|
if (auto terminalTab = _GetTerminalTabImpl(tab))
|
||||||
{
|
{
|
||||||
auto tabActions = terminalTab->BuildStartupActions();
|
auto tabActions = terminalTab->BuildStartupActions();
|
||||||
actions.insert(actions.end(), tabActions.begin(), tabActions.end());
|
actions.insert(actions.end(), std::make_move_iterator(tabActions.begin()), std::make_move_iterator(tabActions.end()));
|
||||||
}
|
}
|
||||||
else if (tab.try_as<SettingsTab>())
|
else if (tab.try_as<SettingsTab>())
|
||||||
{
|
{
|
||||||
|
@ -1311,7 +1330,7 @@ namespace winrt::TerminalApp::implementation
|
||||||
OpenSettingsArgs args{ SettingsTarget::SettingsUI };
|
OpenSettingsArgs args{ SettingsTarget::SettingsUI };
|
||||||
action.Args(args);
|
action.Args(args);
|
||||||
|
|
||||||
actions.push_back(action);
|
actions.emplace_back(std::move(action));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1324,7 +1343,18 @@ namespace winrt::TerminalApp::implementation
|
||||||
SwitchToTabArgs switchToTabArgs{ idx.value() };
|
SwitchToTabArgs switchToTabArgs{ idx.value() };
|
||||||
action.Args(switchToTabArgs);
|
action.Args(switchToTabArgs);
|
||||||
|
|
||||||
actions.push_back(action);
|
actions.emplace_back(std::move(action));
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the user set a custom name, save it
|
||||||
|
if (_WindowName != L"")
|
||||||
|
{
|
||||||
|
ActionAndArgs action;
|
||||||
|
action.Action(ShortcutAction::RenameWindow);
|
||||||
|
RenameWindowArgs args{ _WindowName };
|
||||||
|
action.Args(args);
|
||||||
|
|
||||||
|
actions.emplace_back(std::move(action));
|
||||||
}
|
}
|
||||||
|
|
||||||
WindowLayout layout{};
|
WindowLayout layout{};
|
||||||
|
@ -1337,33 +1367,7 @@ namespace winrt::TerminalApp::implementation
|
||||||
|
|
||||||
layout.InitialSize(windowSize);
|
layout.InitialSize(windowSize);
|
||||||
|
|
||||||
if (_hostingHwnd)
|
return layout;
|
||||||
{
|
|
||||||
// Get the position of the current window. This includes the
|
|
||||||
// non-client already.
|
|
||||||
RECT window{};
|
|
||||||
GetWindowRect(_hostingHwnd.value(), &window);
|
|
||||||
|
|
||||||
// We want to remove the non-client area so calculate that.
|
|
||||||
// We don't have access to the (NonClient)IslandWindow directly so
|
|
||||||
// just replicate the logic.
|
|
||||||
const auto windowStyle = static_cast<DWORD>(GetWindowLong(_hostingHwnd.value(), GWL_STYLE));
|
|
||||||
|
|
||||||
auto dpi = GetDpiForWindow(_hostingHwnd.value());
|
|
||||||
RECT nonClientArea{};
|
|
||||||
LOG_IF_WIN32_BOOL_FALSE(AdjustWindowRectExForDpi(&nonClientArea, windowStyle, false, 0, dpi));
|
|
||||||
|
|
||||||
// The nonClientArea adjustment is negative, so subtract that out.
|
|
||||||
// This way we save the user-visible location of the terminal.
|
|
||||||
LaunchPosition pos{};
|
|
||||||
pos.X = window.left - nonClientArea.left;
|
|
||||||
pos.Y = window.top;
|
|
||||||
|
|
||||||
layout.InitialPosition(pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto state = ApplicationState::SharedInstance();
|
|
||||||
state.PersistedWindowLayouts(winrt::single_threaded_vector<WindowLayout>({ layout }));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
|
@ -1392,8 +1396,9 @@ namespace winrt::TerminalApp::implementation
|
||||||
|
|
||||||
if (ShouldUsePersistedLayout(_settings))
|
if (ShouldUsePersistedLayout(_settings))
|
||||||
{
|
{
|
||||||
PersistWindowLayout();
|
// Don't delete the ApplicationState when all of the tabs are removed.
|
||||||
// don't delete the ApplicationState when all of the tabs are removed.
|
// If there is still a monarch living they will get the event that
|
||||||
|
// a window closed and trigger a new save without this window.
|
||||||
_maintainStateOnTabClose = true;
|
_maintainStateOnTabClose = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2692,52 +2697,40 @@ namespace winrt::TerminalApp::implementation
|
||||||
return _isAlwaysOnTop;
|
return _isAlwaysOnTop;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT TerminalPage::_OnNewConnection(winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection connection)
|
HRESULT TerminalPage::_OnNewConnection(const ConptyConnection& connection)
|
||||||
{
|
{
|
||||||
// We need to be on the UI thread in order for _OpenNewTab to run successfully.
|
// We need to be on the UI thread in order for _OpenNewTab to run successfully.
|
||||||
// HasThreadAccess will return true if we're currently on a UI thread and false otherwise.
|
// HasThreadAccess will return true if we're currently on a UI thread and false otherwise.
|
||||||
// When we're on a COM thread, we'll need to dispatch the calls to the UI thread
|
// When we're on a COM thread, we'll need to dispatch the calls to the UI thread
|
||||||
// and wait on it hence the locking mechanism.
|
// and wait on it hence the locking mechanism.
|
||||||
if (Dispatcher().HasThreadAccess())
|
if (!Dispatcher().HasThreadAccess())
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
NewTerminalArgs newTerminalArgs{};
|
|
||||||
// TODO GH#10952: When we pass the actual commandline (or originating application), the
|
|
||||||
// settings model can choose the right settings based on command matching, or synthesize
|
|
||||||
// a profile from the registry/link settings (TODO GH#9458).
|
|
||||||
// TODO GH#9458: Get and pass the LNK/EXE filenames.
|
|
||||||
// Passing in a commandline forces GetProfileForArgs to use Base Layer instead of Default Profile;
|
|
||||||
// in the future, it can make a better decision based on the value we pull out of the process handle.
|
|
||||||
// TODO GH#5047: When we hang on to the N.T.A., try not to spawn "default... .exe" :)
|
|
||||||
newTerminalArgs.Commandline(L"default-terminal-invocation-placeholder");
|
|
||||||
const auto profile{ _settings.GetProfileForArgs(newTerminalArgs) };
|
|
||||||
const auto settings{ TerminalSettings::CreateWithProfile(_settings, profile, *_bindings) };
|
|
||||||
|
|
||||||
_CreateNewTabWithProfileAndSettings(profile, settings, connection);
|
|
||||||
|
|
||||||
// Request a summon of this window to the foreground
|
|
||||||
_SummonWindowRequestedHandlers(*this, nullptr);
|
|
||||||
}
|
|
||||||
CATCH_RETURN();
|
|
||||||
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
til::latch latch{ 1 };
|
til::latch latch{ 1 };
|
||||||
HRESULT finalVal = S_OK;
|
HRESULT finalVal = S_OK;
|
||||||
|
|
||||||
Dispatcher().RunAsync(CoreDispatcherPriority::Normal, [&]() {
|
Dispatcher().RunAsync(CoreDispatcherPriority::Normal, [&]() {
|
||||||
// Re-running ourselves under the dispatcher will cause us to take the first branch above.
|
|
||||||
finalVal = _OnNewConnection(connection);
|
finalVal = _OnNewConnection(connection);
|
||||||
|
|
||||||
latch.count_down();
|
latch.count_down();
|
||||||
});
|
});
|
||||||
|
|
||||||
latch.wait();
|
latch.wait();
|
||||||
return finalVal;
|
return finalVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
NewTerminalArgs newTerminalArgs;
|
||||||
|
newTerminalArgs.Commandline(connection.Commandline());
|
||||||
|
const auto profile{ _settings.GetProfileForArgs(newTerminalArgs) };
|
||||||
|
const auto settings{ TerminalSettings::CreateWithProfile(_settings, profile, *_bindings) };
|
||||||
|
|
||||||
|
_CreateNewTabWithProfileAndSettings(profile, settings, connection);
|
||||||
|
|
||||||
|
// Request a summon of this window to the foreground
|
||||||
|
_SummonWindowRequestedHandlers(*this, nullptr);
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
CATCH_RETURN()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
|
@ -2890,6 +2883,30 @@ namespace winrt::TerminalApp::implementation
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Method Description:
|
||||||
|
// - Displays a info popup guiding the user into setting their default terminal.
|
||||||
|
void TerminalPage::ShowSetAsDefaultInfoBar() const
|
||||||
|
{
|
||||||
|
if (!CascadiaSettings::IsDefaultTerminalAvailable() || _IsMessageDismissed(InfoBarMessage::SetAsDefault))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the user has already configured any terminal for hand-off we
|
||||||
|
// shouldn't inform them again about the possibility to do so.
|
||||||
|
if (CascadiaSettings::IsDefaultTerminalSet())
|
||||||
|
{
|
||||||
|
_DismissMessage(InfoBarMessage::SetAsDefault);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (const auto infoBar = FindName(L"SetAsDefaultInfoBar").try_as<MUX::Controls::InfoBar>())
|
||||||
|
{
|
||||||
|
TraceLoggingWrite(g_hTerminalAppProvider, "SetAsDefaultTipPresented", TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES), TelemetryPrivacyDataTag(PDT_ProductAndServicePerformance));
|
||||||
|
infoBar.IsOpen(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Function Description:
|
// Function Description:
|
||||||
// - Helper function to get the OS-localized name for the "Touch Keyboard
|
// - Helper function to get the OS-localized name for the "Touch Keyboard
|
||||||
// and Handwriting Panel Service". If we can't open up the service for any
|
// and Handwriting Panel Service". If we can't open up the service for any
|
||||||
|
@ -3106,6 +3123,11 @@ namespace winrt::TerminalApp::implementation
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TerminalPage::SetPersistedLayoutIdx(const uint32_t idx)
|
||||||
|
{
|
||||||
|
_loadFromPersistedLayoutIdx = idx;
|
||||||
|
}
|
||||||
|
|
||||||
void TerminalPage::SetNumberOfOpenWindows(const uint64_t num)
|
void TerminalPage::SetNumberOfOpenWindows(const uint64_t num)
|
||||||
{
|
{
|
||||||
_numOpenWindows = num;
|
_numOpenWindows = num;
|
||||||
|
@ -3305,6 +3327,40 @@ namespace winrt::TerminalApp::implementation
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Method Description:
|
||||||
|
// - Persists the user's choice not to show the information bar warning about "Windows Terminal can be set as your default terminal application"
|
||||||
|
// Then hides this information buffer.
|
||||||
|
// Arguments:
|
||||||
|
// - <none>
|
||||||
|
// Return Value:
|
||||||
|
// - <none>
|
||||||
|
void TerminalPage::_SetAsDefaultDismissHandler(const IInspectable& /*sender*/, const IInspectable& /*args*/)
|
||||||
|
{
|
||||||
|
_DismissMessage(InfoBarMessage::SetAsDefault);
|
||||||
|
if (const auto infoBar = FindName(L"SetAsDefaultInfoBar").try_as<MUX::Controls::InfoBar>())
|
||||||
|
{
|
||||||
|
infoBar.IsOpen(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
TraceLoggingWrite(g_hTerminalAppProvider, "SetAsDefaultTipDismissed", TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES), TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
|
||||||
|
|
||||||
|
_FocusCurrentTab(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method Description:
|
||||||
|
// - Dismisses the Default Terminal tip and opens the settings.
|
||||||
|
void TerminalPage::_SetAsDefaultOpenSettingsHandler(const IInspectable& /*sender*/, const IInspectable& /*args*/)
|
||||||
|
{
|
||||||
|
if (const auto infoBar = FindName(L"SetAsDefaultInfoBar").try_as<MUX::Controls::InfoBar>())
|
||||||
|
{
|
||||||
|
infoBar.IsOpen(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
TraceLoggingWrite(g_hTerminalAppProvider, "SetAsDefaultTipInteracted", TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES), TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
|
||||||
|
|
||||||
|
_OpenSettingsUI();
|
||||||
|
}
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
// - Checks whether information bar message was dismissed earlier (in the application state)
|
// - Checks whether information bar message was dismissed earlier (in the application state)
|
||||||
// Arguments:
|
// Arguments:
|
||||||
|
@ -3334,13 +3390,20 @@ namespace winrt::TerminalApp::implementation
|
||||||
// - <none>
|
// - <none>
|
||||||
void TerminalPage::_DismissMessage(const InfoBarMessage& message)
|
void TerminalPage::_DismissMessage(const InfoBarMessage& message)
|
||||||
{
|
{
|
||||||
auto dismissedMessages = ApplicationState::SharedInstance().DismissedMessages();
|
const auto applicationState = ApplicationState::SharedInstance();
|
||||||
if (!dismissedMessages)
|
std::vector<InfoBarMessage> messages;
|
||||||
|
|
||||||
|
if (const auto values = applicationState.DismissedMessages())
|
||||||
{
|
{
|
||||||
dismissedMessages = winrt::single_threaded_vector<InfoBarMessage>();
|
messages.resize(values.Size());
|
||||||
|
values.GetMany(0, messages);
|
||||||
}
|
}
|
||||||
|
|
||||||
dismissedMessages.Append(message);
|
if (std::none_of(messages.begin(), messages.end(), [&](const auto& m) { return m == message; }))
|
||||||
ApplicationState::SharedInstance().DismissedMessages(dismissedMessages);
|
{
|
||||||
|
messages.emplace_back(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
applicationState.DismissedMessages(std::move(messages));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,6 +59,9 @@ namespace winrt::TerminalApp::implementation
|
||||||
void Create();
|
void Create();
|
||||||
|
|
||||||
bool ShouldUsePersistedLayout(Microsoft::Terminal::Settings::Model::CascadiaSettings& settings) const;
|
bool ShouldUsePersistedLayout(Microsoft::Terminal::Settings::Model::CascadiaSettings& settings) const;
|
||||||
|
std::optional<uint32_t> LoadPersistedLayoutIdx(Microsoft::Terminal::Settings::Model::CascadiaSettings& settings) const;
|
||||||
|
winrt::Microsoft::Terminal::Settings::Model::WindowLayout LoadPersistedLayout(Microsoft::Terminal::Settings::Model::CascadiaSettings& settings) const;
|
||||||
|
Microsoft::Terminal::Settings::Model::WindowLayout GetWindowLayout();
|
||||||
|
|
||||||
winrt::fire_and_forget NewTerminalByDrop(winrt::Windows::UI::Xaml::DragEventArgs& e);
|
winrt::fire_and_forget NewTerminalByDrop(winrt::Windows::UI::Xaml::DragEventArgs& e);
|
||||||
|
|
||||||
|
@ -82,7 +85,6 @@ namespace winrt::TerminalApp::implementation
|
||||||
bool AlwaysOnTop() const;
|
bool AlwaysOnTop() const;
|
||||||
|
|
||||||
void SetStartupActions(std::vector<Microsoft::Terminal::Settings::Model::ActionAndArgs>& actions);
|
void SetStartupActions(std::vector<Microsoft::Terminal::Settings::Model::ActionAndArgs>& actions);
|
||||||
void PersistWindowLayout();
|
|
||||||
|
|
||||||
void SetInboundListener(bool isEmbedding);
|
void SetInboundListener(bool isEmbedding);
|
||||||
static std::vector<Microsoft::Terminal::Settings::Model::ActionAndArgs> ConvertExecuteCommandlineToActions(const Microsoft::Terminal::Settings::Model::ExecuteCommandlineArgs& args);
|
static std::vector<Microsoft::Terminal::Settings::Model::ActionAndArgs> ConvertExecuteCommandlineToActions(const Microsoft::Terminal::Settings::Model::ExecuteCommandlineArgs& args);
|
||||||
|
@ -93,6 +95,7 @@ namespace winrt::TerminalApp::implementation
|
||||||
winrt::TerminalApp::TaskbarState TaskbarState() const;
|
winrt::TerminalApp::TaskbarState TaskbarState() const;
|
||||||
|
|
||||||
void ShowKeyboardServiceWarning() const;
|
void ShowKeyboardServiceWarning() const;
|
||||||
|
void ShowSetAsDefaultInfoBar() const;
|
||||||
winrt::hstring KeyboardServiceDisabledText();
|
winrt::hstring KeyboardServiceDisabledText();
|
||||||
|
|
||||||
winrt::fire_and_forget IdentifyWindow();
|
winrt::fire_and_forget IdentifyWindow();
|
||||||
|
@ -111,6 +114,7 @@ namespace winrt::TerminalApp::implementation
|
||||||
void WindowId(const uint64_t& value);
|
void WindowId(const uint64_t& value);
|
||||||
|
|
||||||
void SetNumberOfOpenWindows(const uint64_t value);
|
void SetNumberOfOpenWindows(const uint64_t value);
|
||||||
|
void SetPersistedLayoutIdx(const uint32_t value);
|
||||||
|
|
||||||
winrt::hstring WindowIdForDisplay() const noexcept;
|
winrt::hstring WindowIdForDisplay() const noexcept;
|
||||||
winrt::hstring WindowNameForDisplay() const noexcept;
|
winrt::hstring WindowNameForDisplay() const noexcept;
|
||||||
|
@ -133,6 +137,7 @@ namespace winrt::TerminalApp::implementation
|
||||||
TYPED_EVENT(RenameWindowRequested, Windows::Foundation::IInspectable, winrt::TerminalApp::RenameWindowRequestedArgs);
|
TYPED_EVENT(RenameWindowRequested, Windows::Foundation::IInspectable, winrt::TerminalApp::RenameWindowRequestedArgs);
|
||||||
TYPED_EVENT(IsQuakeWindowChanged, IInspectable, IInspectable);
|
TYPED_EVENT(IsQuakeWindowChanged, IInspectable, IInspectable);
|
||||||
TYPED_EVENT(SummonWindowRequested, IInspectable, IInspectable);
|
TYPED_EVENT(SummonWindowRequested, IInspectable, IInspectable);
|
||||||
|
TYPED_EVENT(CloseRequested, IInspectable, IInspectable);
|
||||||
TYPED_EVENT(OpenSystemMenu, IInspectable, IInspectable);
|
TYPED_EVENT(OpenSystemMenu, IInspectable, IInspectable);
|
||||||
TYPED_EVENT(QuitRequested, IInspectable, IInspectable);
|
TYPED_EVENT(QuitRequested, IInspectable, IInspectable);
|
||||||
|
|
||||||
|
@ -166,6 +171,7 @@ namespace winrt::TerminalApp::implementation
|
||||||
bool _isAlwaysOnTop{ false };
|
bool _isAlwaysOnTop{ false };
|
||||||
winrt::hstring _WindowName{};
|
winrt::hstring _WindowName{};
|
||||||
uint64_t _WindowId{ 0 };
|
uint64_t _WindowId{ 0 };
|
||||||
|
std::optional<uint32_t> _loadFromPersistedLayoutIdx{};
|
||||||
uint64_t _numOpenWindows{ 0 };
|
uint64_t _numOpenWindows{ 0 };
|
||||||
|
|
||||||
bool _maintainStateOnTabClose{ false };
|
bool _maintainStateOnTabClose{ false };
|
||||||
|
@ -257,6 +263,26 @@ namespace winrt::TerminalApp::implementation
|
||||||
bool _SwapPane(const Microsoft::Terminal::Settings::Model::FocusDirection& direction);
|
bool _SwapPane(const Microsoft::Terminal::Settings::Model::FocusDirection& direction);
|
||||||
bool _MovePane(const uint32_t tabIdx);
|
bool _MovePane(const uint32_t tabIdx);
|
||||||
|
|
||||||
|
template<typename F>
|
||||||
|
bool _ApplyToActiveControls(F f)
|
||||||
|
{
|
||||||
|
if (const auto tab{ _GetFocusedTabImpl() })
|
||||||
|
{
|
||||||
|
if (const auto activePane = tab->GetActivePane())
|
||||||
|
{
|
||||||
|
activePane->WalkTree([&](auto p) {
|
||||||
|
if (const auto& control{ p->GetTerminalControl() })
|
||||||
|
{
|
||||||
|
f(control);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
winrt::Microsoft::Terminal::Control::TermControl _GetActiveControl();
|
winrt::Microsoft::Terminal::Control::TermControl _GetActiveControl();
|
||||||
std::optional<uint32_t> _GetFocusedTabIndex() const noexcept;
|
std::optional<uint32_t> _GetFocusedTabIndex() const noexcept;
|
||||||
TerminalApp::TabBase _GetFocusedTab() const noexcept;
|
TerminalApp::TabBase _GetFocusedTab() const noexcept;
|
||||||
|
@ -360,9 +386,9 @@ namespace winrt::TerminalApp::implementation
|
||||||
void _EndPreviewColorScheme();
|
void _EndPreviewColorScheme();
|
||||||
void _PreviewColorScheme(const Microsoft::Terminal::Settings::Model::SetColorSchemeArgs& args);
|
void _PreviewColorScheme(const Microsoft::Terminal::Settings::Model::SetColorSchemeArgs& args);
|
||||||
winrt::Microsoft::Terminal::Settings::Model::Command _lastPreviewedCommand{ nullptr };
|
winrt::Microsoft::Terminal::Settings::Model::Command _lastPreviewedCommand{ nullptr };
|
||||||
winrt::Microsoft::Terminal::Settings::Model::TerminalSettings _originalSettings{ nullptr };
|
std::vector<std::function<void()>> _restorePreviewFuncs{};
|
||||||
|
|
||||||
HRESULT _OnNewConnection(winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection connection);
|
HRESULT _OnNewConnection(const winrt::Microsoft::Terminal::TerminalConnection::ConptyConnection& connection);
|
||||||
void _HandleToggleInboundPty(const IInspectable& sender, const Microsoft::Terminal::Settings::Model::ActionEventArgs& args);
|
void _HandleToggleInboundPty(const IInspectable& sender, const Microsoft::Terminal::Settings::Model::ActionEventArgs& args);
|
||||||
|
|
||||||
void _WindowRenamerActionClick(const IInspectable& sender, const IInspectable& eventArgs);
|
void _WindowRenamerActionClick(const IInspectable& sender, const IInspectable& eventArgs);
|
||||||
|
@ -378,6 +404,8 @@ namespace winrt::TerminalApp::implementation
|
||||||
winrt::fire_and_forget _ConnectionStateChangedHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args) const;
|
winrt::fire_and_forget _ConnectionStateChangedHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args) const;
|
||||||
void _CloseOnExitInfoDismissHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args) const;
|
void _CloseOnExitInfoDismissHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args) const;
|
||||||
void _KeyboardServiceWarningInfoDismissHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args) const;
|
void _KeyboardServiceWarningInfoDismissHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args) const;
|
||||||
|
void _SetAsDefaultDismissHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args);
|
||||||
|
void _SetAsDefaultOpenSettingsHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args);
|
||||||
static bool _IsMessageDismissed(const winrt::Microsoft::Terminal::Settings::Model::InfoBarMessage& message);
|
static bool _IsMessageDismissed(const winrt::Microsoft::Terminal::Settings::Model::InfoBarMessage& message);
|
||||||
static void _DismissMessage(const winrt::Microsoft::Terminal::Settings::Model::InfoBarMessage& message);
|
static void _DismissMessage(const winrt::Microsoft::Terminal::Settings::Model::InfoBarMessage& message);
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,6 @@ namespace TerminalApp
|
||||||
UInt64 WindowId;
|
UInt64 WindowId;
|
||||||
String WindowNameForDisplay { get; };
|
String WindowNameForDisplay { get; };
|
||||||
String WindowIdForDisplay { get; };
|
String WindowIdForDisplay { get; };
|
||||||
void SetNumberOfOpenWindows(UInt64 num);
|
|
||||||
void RenameFailed();
|
void RenameFailed();
|
||||||
Boolean IsQuakeWindow();
|
Boolean IsQuakeWindow();
|
||||||
|
|
||||||
|
@ -58,6 +57,7 @@ namespace TerminalApp
|
||||||
event Windows.Foundation.TypedEventHandler<Object, RenameWindowRequestedArgs> RenameWindowRequested;
|
event Windows.Foundation.TypedEventHandler<Object, RenameWindowRequestedArgs> RenameWindowRequested;
|
||||||
event Windows.Foundation.TypedEventHandler<Object, Object> IsQuakeWindowChanged;
|
event Windows.Foundation.TypedEventHandler<Object, Object> IsQuakeWindowChanged;
|
||||||
event Windows.Foundation.TypedEventHandler<Object, Object> SummonWindowRequested;
|
event Windows.Foundation.TypedEventHandler<Object, Object> SummonWindowRequested;
|
||||||
|
event Windows.Foundation.TypedEventHandler<Object, Object> CloseRequested;
|
||||||
event Windows.Foundation.TypedEventHandler<Object, Object> OpenSystemMenu;
|
event Windows.Foundation.TypedEventHandler<Object, Object> OpenSystemMenu;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -141,6 +141,20 @@
|
||||||
Click="_CloseOnExitInfoDismissHandler" />
|
Click="_CloseOnExitInfoDismissHandler" />
|
||||||
</mux:InfoBar.ActionButton>
|
</mux:InfoBar.ActionButton>
|
||||||
</mux:InfoBar>
|
</mux:InfoBar>
|
||||||
|
|
||||||
|
<mux:InfoBar x:Name="SetAsDefaultInfoBar"
|
||||||
|
x:Uid="SetAsDefaultInfoBar"
|
||||||
|
x:Load="False"
|
||||||
|
CloseButtonClick="_SetAsDefaultDismissHandler"
|
||||||
|
IsClosable="True"
|
||||||
|
IsIconVisible="True"
|
||||||
|
IsOpen="False"
|
||||||
|
Severity="Informational">
|
||||||
|
<mux:InfoBar.ActionButton>
|
||||||
|
<HyperlinkButton x:Uid="SetAsDefaultTip_OpenSettingsLink"
|
||||||
|
Click="_SetAsDefaultOpenSettingsHandler" />
|
||||||
|
</mux:InfoBar.ActionButton>
|
||||||
|
</mux:InfoBar>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
|
|
|
@ -67,8 +67,11 @@ namespace winrt::TerminalApp::implementation
|
||||||
_rootPane->FocusPane(firstId);
|
_rootPane->FocusPane(firstId);
|
||||||
_activePane = _rootPane->GetActivePane();
|
_activePane = _rootPane->GetActivePane();
|
||||||
}
|
}
|
||||||
// Set the active control
|
// If the focused pane is a leaf, add it to the MRU panes
|
||||||
_mruPanes.insert(_mruPanes.begin(), _activePane->Id().value());
|
if (const auto id = _activePane->Id())
|
||||||
|
{
|
||||||
|
_mruPanes.insert(_mruPanes.begin(), id.value());
|
||||||
|
}
|
||||||
|
|
||||||
_Setup();
|
_Setup();
|
||||||
}
|
}
|
||||||
|
@ -180,8 +183,8 @@ namespace winrt::TerminalApp::implementation
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
// - Returns nullptr if no children of this tab were the last control to be
|
// - Returns nullptr if no children of this tab were the last control to be
|
||||||
// focused, or the TermControl that _was_ the last control to be focused (if
|
// focused, the active control of the current pane, or the last active child control
|
||||||
// there was one).
|
// of the active pane if it is a parent.
|
||||||
// - This control might not currently be focused, if the tab itself is not
|
// - This control might not currently be focused, if the tab itself is not
|
||||||
// currently focused.
|
// currently focused.
|
||||||
// Arguments:
|
// Arguments:
|
||||||
|
@ -193,7 +196,7 @@ namespace winrt::TerminalApp::implementation
|
||||||
{
|
{
|
||||||
if (_activePane)
|
if (_activePane)
|
||||||
{
|
{
|
||||||
return _activePane->GetTerminalControl();
|
return _activePane->GetLastFocusedTerminalControl();
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -390,6 +393,10 @@ namespace winrt::TerminalApp::implementation
|
||||||
{
|
{
|
||||||
return _runtimeTabText;
|
return _runtimeTabText;
|
||||||
}
|
}
|
||||||
|
if (!_activePane->_IsLeaf())
|
||||||
|
{
|
||||||
|
return RS_(L"MultiplePanes");
|
||||||
|
}
|
||||||
const auto lastFocusedControl = GetActiveTerminalControl();
|
const auto lastFocusedControl = GetActiveTerminalControl();
|
||||||
return lastFocusedControl ? lastFocusedControl.Title() : L"";
|
return lastFocusedControl ? lastFocusedControl.Title() : L"";
|
||||||
}
|
}
|
||||||
|
@ -450,12 +457,25 @@ namespace winrt::TerminalApp::implementation
|
||||||
// 1 for the child after the first split.
|
// 1 for the child after the first split.
|
||||||
auto state = _rootPane->BuildStartupActions(0, 1);
|
auto state = _rootPane->BuildStartupActions(0, 1);
|
||||||
|
|
||||||
ActionAndArgs newTabAction{};
|
{
|
||||||
newTabAction.Action(ShortcutAction::NewTab);
|
ActionAndArgs newTabAction{};
|
||||||
NewTabArgs newTabArgs{ state.firstPane->GetTerminalArgsForPane() };
|
newTabAction.Action(ShortcutAction::NewTab);
|
||||||
newTabAction.Args(newTabArgs);
|
NewTabArgs newTabArgs{ state.firstPane->GetTerminalArgsForPane() };
|
||||||
|
newTabAction.Args(newTabArgs);
|
||||||
|
|
||||||
state.args.emplace(state.args.begin(), std::move(newTabAction));
|
state.args.emplace(state.args.begin(), std::move(newTabAction));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_runtimeTabColor)
|
||||||
|
{
|
||||||
|
ActionAndArgs setColorAction{};
|
||||||
|
setColorAction.Action(ShortcutAction::SetTabColor);
|
||||||
|
|
||||||
|
SetTabColorArgs setColorArgs{ _runtimeTabColor.value() };
|
||||||
|
setColorAction.Args(setColorArgs);
|
||||||
|
|
||||||
|
state.args.emplace_back(std::move(setColorAction));
|
||||||
|
}
|
||||||
|
|
||||||
// If we only have one arg, we only have 1 pane so we don't need any
|
// If we only have one arg, we only have 1 pane so we don't need any
|
||||||
// special focus logic
|
// special focus logic
|
||||||
|
@ -501,19 +521,14 @@ namespace winrt::TerminalApp::implementation
|
||||||
// either the first or second child, but this will always return the
|
// either the first or second child, but this will always return the
|
||||||
// original pane first.
|
// original pane first.
|
||||||
auto [original, newPane] = _activePane->Split(splitType, splitSize, profile, control);
|
auto [original, newPane] = _activePane->Split(splitType, splitSize, profile, control);
|
||||||
|
// The active pane has an id if it is a leaf
|
||||||
if (activePaneId)
|
if (activePaneId)
|
||||||
{
|
{
|
||||||
original->Id(activePaneId.value());
|
original->Id(activePaneId.value());
|
||||||
newPane->Id(_nextPaneId);
|
|
||||||
++_nextPaneId;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
original->Id(_nextPaneId);
|
|
||||||
++_nextPaneId;
|
|
||||||
newPane->Id(_nextPaneId);
|
|
||||||
++_nextPaneId;
|
|
||||||
}
|
}
|
||||||
|
newPane->Id(_nextPaneId);
|
||||||
|
++_nextPaneId;
|
||||||
|
|
||||||
_activePane = original;
|
_activePane = original;
|
||||||
|
|
||||||
// Add a event handlers to the new panes' GotFocus event. When the pane
|
// Add a event handlers to the new panes' GotFocus event. When the pane
|
||||||
|
@ -538,8 +553,8 @@ namespace winrt::TerminalApp::implementation
|
||||||
// - The removed pane, if the remove succeeded.
|
// - The removed pane, if the remove succeeded.
|
||||||
std::shared_ptr<Pane> TerminalTab::DetachPane()
|
std::shared_ptr<Pane> TerminalTab::DetachPane()
|
||||||
{
|
{
|
||||||
// if we only have one pane, remove it entirely
|
// if we only have one pane, or the focused pane is the root, remove it
|
||||||
// and close this tab
|
// entirely and close this tab
|
||||||
if (_rootPane == _activePane)
|
if (_rootPane == _activePane)
|
||||||
{
|
{
|
||||||
return DetachRoot();
|
return DetachRoot();
|
||||||
|
@ -614,16 +629,12 @@ namespace winrt::TerminalApp::implementation
|
||||||
// Add the new pane as an automatic split on the active pane.
|
// Add the new pane as an automatic split on the active pane.
|
||||||
auto first = _activePane->AttachPane(pane, SplitDirection::Automatic);
|
auto first = _activePane->AttachPane(pane, SplitDirection::Automatic);
|
||||||
|
|
||||||
// under current assumptions this condition should always be true.
|
// This will be true if the original _activePane is a leaf pane.
|
||||||
|
// If it is a parent pane then we don't want to set an ID on it.
|
||||||
if (previousId)
|
if (previousId)
|
||||||
{
|
{
|
||||||
first->Id(previousId.value());
|
first->Id(previousId.value());
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
first->Id(_nextPaneId);
|
|
||||||
++_nextPaneId;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update with event handlers on the new child.
|
// Update with event handlers on the new child.
|
||||||
_activePane = first;
|
_activePane = first;
|
||||||
|
@ -699,7 +710,10 @@ namespace winrt::TerminalApp::implementation
|
||||||
// throughout the entire tree.
|
// throughout the entire tree.
|
||||||
if (const auto newFocus = _rootPane->NavigateDirection(_activePane, direction, _mruPanes))
|
if (const auto newFocus = _rootPane->NavigateDirection(_activePane, direction, _mruPanes))
|
||||||
{
|
{
|
||||||
|
// Mark that we want the active pane to changed
|
||||||
|
_changingActivePane = true;
|
||||||
const auto res = _rootPane->FocusPane(newFocus);
|
const auto res = _rootPane->FocusPane(newFocus);
|
||||||
|
_changingActivePane = false;
|
||||||
|
|
||||||
if (_zoomedPane)
|
if (_zoomedPane)
|
||||||
{
|
{
|
||||||
|
@ -722,11 +736,22 @@ namespace winrt::TerminalApp::implementation
|
||||||
// - true if two panes were swapped.
|
// - true if two panes were swapped.
|
||||||
bool TerminalTab::SwapPane(const FocusDirection& direction)
|
bool TerminalTab::SwapPane(const FocusDirection& direction)
|
||||||
{
|
{
|
||||||
|
// You cannot swap panes with the parent/child pane because of the
|
||||||
|
// circular reference.
|
||||||
|
if (direction == FocusDirection::Parent || direction == FocusDirection::Child)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
// NOTE: This _must_ be called on the root pane, so that it can propagate
|
// NOTE: This _must_ be called on the root pane, so that it can propagate
|
||||||
// throughout the entire tree.
|
// throughout the entire tree.
|
||||||
if (auto neighbor = _rootPane->NavigateDirection(_activePane, direction, _mruPanes))
|
if (auto neighbor = _rootPane->NavigateDirection(_activePane, direction, _mruPanes))
|
||||||
{
|
{
|
||||||
return _rootPane->SwapPanes(_activePane, neighbor);
|
// SwapPanes will refocus the terminal to make sure that it has focus
|
||||||
|
// even after moving.
|
||||||
|
_changingActivePane = true;
|
||||||
|
const auto res = _rootPane->SwapPanes(_activePane, neighbor);
|
||||||
|
_changingActivePane = false;
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -734,7 +759,10 @@ namespace winrt::TerminalApp::implementation
|
||||||
|
|
||||||
bool TerminalTab::FocusPane(const uint32_t id)
|
bool TerminalTab::FocusPane(const uint32_t id)
|
||||||
{
|
{
|
||||||
return _rootPane->FocusPane(id);
|
_changingActivePane = true;
|
||||||
|
const auto res = _rootPane->FocusPane(id);
|
||||||
|
_changingActivePane = false;
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
|
@ -1027,7 +1055,7 @@ namespace winrt::TerminalApp::implementation
|
||||||
auto weakThis{ get_weak() };
|
auto weakThis{ get_weak() };
|
||||||
std::weak_ptr<Pane> weakPane{ pane };
|
std::weak_ptr<Pane> weakPane{ pane };
|
||||||
|
|
||||||
auto gotFocusToken = pane->GotFocus([weakThis](std::shared_ptr<Pane> sender) {
|
auto gotFocusToken = pane->GotFocus([weakThis](std::shared_ptr<Pane> sender, WUX::FocusState focus) {
|
||||||
// Do nothing if the Tab's lifetime is expired or pane isn't new.
|
// Do nothing if the Tab's lifetime is expired or pane isn't new.
|
||||||
auto tab{ weakThis.get() };
|
auto tab{ weakThis.get() };
|
||||||
|
|
||||||
|
@ -1035,8 +1063,20 @@ namespace winrt::TerminalApp::implementation
|
||||||
{
|
{
|
||||||
if (sender != tab->_activePane)
|
if (sender != tab->_activePane)
|
||||||
{
|
{
|
||||||
tab->_UpdateActivePane(sender);
|
auto senderIsChild = tab->_activePane->_HasChild(sender);
|
||||||
tab->_RecalculateAndApplyTabColor();
|
|
||||||
|
// Only move focus if we the program moved focus, or the
|
||||||
|
// user moved with their mouse. This is a problem because a
|
||||||
|
// pane isn't a control itself, and if we have the parent
|
||||||
|
// focused we are fine if the terminal control is focused,
|
||||||
|
// but we don't want to update the active pane.
|
||||||
|
if (!senderIsChild ||
|
||||||
|
(focus == WUX::FocusState::Programmatic && tab->_changingActivePane) ||
|
||||||
|
focus == WUX::FocusState::Pointer)
|
||||||
|
{
|
||||||
|
tab->_UpdateActivePane(sender);
|
||||||
|
tab->_RecalculateAndApplyTabColor();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
tab->_focusState = WUX::FocusState::Programmatic;
|
tab->_focusState = WUX::FocusState::Programmatic;
|
||||||
// This tab has gained focus, remove the bell indicator if it is active
|
// This tab has gained focus, remove the bell indicator if it is active
|
||||||
|
@ -1071,8 +1111,19 @@ namespace winrt::TerminalApp::implementation
|
||||||
tab->Content(tab->_rootPane->GetRootElement());
|
tab->Content(tab->_rootPane->GetRootElement());
|
||||||
tab->ExitZoom();
|
tab->ExitZoom();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto pane = weakPane.lock())
|
if (auto pane = weakPane.lock())
|
||||||
{
|
{
|
||||||
|
// When a parent pane is selected, but one of its children
|
||||||
|
// close out under it we still need to update title/focus information
|
||||||
|
// but the GotFocus handler will rightly see that the _activePane
|
||||||
|
// did not actually change. Triggering
|
||||||
|
if (pane != tab->_activePane && !tab->_activePane->_IsLeaf())
|
||||||
|
{
|
||||||
|
co_await winrt::resume_foreground(tab->Content().Dispatcher());
|
||||||
|
tab->_UpdateActivePane(tab->_activePane);
|
||||||
|
}
|
||||||
|
|
||||||
for (auto i = tab->_mruPanes.begin(); i != tab->_mruPanes.end(); ++i)
|
for (auto i = tab->_mruPanes.begin(); i != tab->_mruPanes.end(); ++i)
|
||||||
{
|
{
|
||||||
if (*i == pane->Id())
|
if (*i == pane->Id())
|
||||||
|
@ -1290,11 +1341,13 @@ namespace winrt::TerminalApp::implementation
|
||||||
// - The tab's color, if any
|
// - The tab's color, if any
|
||||||
std::optional<winrt::Windows::UI::Color> TerminalTab::GetTabColor()
|
std::optional<winrt::Windows::UI::Color> TerminalTab::GetTabColor()
|
||||||
{
|
{
|
||||||
const auto currControlColor{ GetActiveTerminalControl().TabColor() };
|
|
||||||
std::optional<winrt::Windows::UI::Color> controlTabColor;
|
std::optional<winrt::Windows::UI::Color> controlTabColor;
|
||||||
if (currControlColor != nullptr)
|
if (const auto& control = GetActiveTerminalControl())
|
||||||
{
|
{
|
||||||
controlTabColor = currControlColor.Value();
|
if (const auto color = control.TabColor())
|
||||||
|
{
|
||||||
|
controlTabColor = color.Value();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// A Tab's color will be the result of layering a variety of sources,
|
// A Tab's color will be the result of layering a variety of sources,
|
||||||
|
@ -1407,6 +1460,10 @@ namespace winrt::TerminalApp::implementation
|
||||||
// TabViewItem().Background() only sets the color of the tab background
|
// TabViewItem().Background() only sets the color of the tab background
|
||||||
// when the TabViewItem is unselected. So we still need to set the other
|
// when the TabViewItem is unselected. So we still need to set the other
|
||||||
// properties ourselves.
|
// properties ourselves.
|
||||||
|
//
|
||||||
|
// In GH#11294 we thought we'd still need to set
|
||||||
|
// TabViewItemHeaderBackground manually, but GH#11382 discovered that
|
||||||
|
// Background() was actually okay after all.
|
||||||
TabViewItem().Background(deselectedTabBrush);
|
TabViewItem().Background(deselectedTabBrush);
|
||||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderBackgroundSelected"), selectedTabBrush);
|
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderBackgroundSelected"), selectedTabBrush);
|
||||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderBackgroundPointerOver"), hoverTabBrush);
|
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderBackgroundPointerOver"), hoverTabBrush);
|
||||||
|
@ -1453,6 +1510,7 @@ namespace winrt::TerminalApp::implementation
|
||||||
void TerminalTab::_ClearTabBackgroundColor()
|
void TerminalTab::_ClearTabBackgroundColor()
|
||||||
{
|
{
|
||||||
winrt::hstring keys[] = {
|
winrt::hstring keys[] = {
|
||||||
|
L"TabViewItemHeaderBackground",
|
||||||
L"TabViewItemHeaderBackgroundSelected",
|
L"TabViewItemHeaderBackgroundSelected",
|
||||||
L"TabViewItemHeaderBackgroundPointerOver",
|
L"TabViewItemHeaderBackgroundPointerOver",
|
||||||
L"TabViewItemHeaderForeground",
|
L"TabViewItemHeaderForeground",
|
||||||
|
@ -1473,8 +1531,10 @@ namespace winrt::TerminalApp::implementation
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear out the Background.
|
// GH#11382 DON'T set the background to null. If you do that, then the
|
||||||
TabViewItem().Background(nullptr);
|
// tab won't be hit testable at all. Transparent, however, is a totally
|
||||||
|
// valid hit test target. That makes sense.
|
||||||
|
TabViewItem().Background(WUX::Media::SolidColorBrush{ Windows::UI::Colors::Transparent() });
|
||||||
|
|
||||||
_RefreshVisualState();
|
_RefreshVisualState();
|
||||||
_colorCleared();
|
_colorCleared();
|
||||||
|
@ -1585,6 +1645,11 @@ namespace winrt::TerminalApp::implementation
|
||||||
|
|
||||||
void TerminalTab::EnterZoom()
|
void TerminalTab::EnterZoom()
|
||||||
{
|
{
|
||||||
|
// Clear the content first, because with parent focusing it is possible
|
||||||
|
// to zoom the root pane, but setting the content will not trigger the
|
||||||
|
// property changed event since it is the same and you would end up with
|
||||||
|
// an empty tab.
|
||||||
|
Content(nullptr);
|
||||||
_zoomedPane = _activePane;
|
_zoomedPane = _activePane;
|
||||||
_rootPane->Maximize(_zoomedPane);
|
_rootPane->Maximize(_zoomedPane);
|
||||||
// Update the tab header to show the magnifying glass
|
// Update the tab header to show the magnifying glass
|
||||||
|
@ -1593,6 +1658,7 @@ namespace winrt::TerminalApp::implementation
|
||||||
}
|
}
|
||||||
void TerminalTab::ExitZoom()
|
void TerminalTab::ExitZoom()
|
||||||
{
|
{
|
||||||
|
Content(nullptr);
|
||||||
_rootPane->Restore(_zoomedPane);
|
_rootPane->Restore(_zoomedPane);
|
||||||
_zoomedPane = nullptr;
|
_zoomedPane = nullptr;
|
||||||
// Update the tab header to hide the magnifying glass
|
// Update the tab header to hide the magnifying glass
|
||||||
|
@ -1607,13 +1673,34 @@ namespace winrt::TerminalApp::implementation
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
// - Toggle read-only mode on the active pane
|
// - Toggle read-only mode on the active pane
|
||||||
|
// - If a parent pane is selected, this will ensure that all children have
|
||||||
|
// the same read-only status.
|
||||||
void TerminalTab::TogglePaneReadOnly()
|
void TerminalTab::TogglePaneReadOnly()
|
||||||
{
|
{
|
||||||
auto control = GetActiveTerminalControl();
|
auto hasReadOnly = false;
|
||||||
if (control)
|
auto allReadOnly = true;
|
||||||
{
|
_activePane->WalkTree([&](auto p) {
|
||||||
control.ToggleReadOnly();
|
if (const auto& control{ p->GetTerminalControl() })
|
||||||
}
|
{
|
||||||
|
hasReadOnly |= control.ReadOnly();
|
||||||
|
allReadOnly &= control.ReadOnly();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
_activePane->WalkTree([&](auto p) {
|
||||||
|
if (const auto& control{ p->GetTerminalControl() })
|
||||||
|
{
|
||||||
|
// If all controls have the same read only state then just toggle
|
||||||
|
if (allReadOnly || !hasReadOnly)
|
||||||
|
{
|
||||||
|
control.ToggleReadOnly();
|
||||||
|
}
|
||||||
|
// otherwise set to all read only.
|
||||||
|
else if (!control.ReadOnly())
|
||||||
|
{
|
||||||
|
control.ToggleReadOnly();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
|
|
|
@ -139,6 +139,7 @@ namespace winrt::TerminalApp::implementation
|
||||||
|
|
||||||
bool _receivedKeyDown{ false };
|
bool _receivedKeyDown{ false };
|
||||||
bool _iconHidden{ false };
|
bool _iconHidden{ false };
|
||||||
|
bool _changingActivePane{ false };
|
||||||
|
|
||||||
winrt::hstring _runtimeTabText{};
|
winrt::hstring _runtimeTabText{};
|
||||||
bool _inRename{ false };
|
bool _inRename{ false };
|
||||||
|
|
|
@ -99,29 +99,57 @@ static HRESULT _duplicateHandle(const HANDLE in, HANDLE& out) noexcept
|
||||||
// from the registered handler event function.
|
// from the registered handler event function.
|
||||||
HRESULT CTerminalHandoff::EstablishPtyHandoff(HANDLE in, HANDLE out, HANDLE signal, HANDLE ref, HANDLE server, HANDLE client)
|
HRESULT CTerminalHandoff::EstablishPtyHandoff(HANDLE in, HANDLE out, HANDLE signal, HANDLE ref, HANDLE server, HANDLE client)
|
||||||
{
|
{
|
||||||
// Stash a local copy of _pfnHandoff before we stop listening.
|
try
|
||||||
auto localPfnHandoff = _pfnHandoff;
|
{
|
||||||
|
// Stash a local copy of _pfnHandoff before we stop listening.
|
||||||
|
auto localPfnHandoff = _pfnHandoff;
|
||||||
|
|
||||||
// Because we are REGCLS_SINGLEUSE... we need to `CoRevokeClassObject` after we handle this ONE call.
|
// Because we are REGCLS_SINGLEUSE... we need to `CoRevokeClassObject` after we handle this ONE call.
|
||||||
// COM does not automatically clean that up for us. We must do it.
|
// COM does not automatically clean that up for us. We must do it.
|
||||||
s_StopListening();
|
s_StopListening();
|
||||||
|
|
||||||
std::unique_lock lock{ _mtx };
|
std::unique_lock lock{ _mtx };
|
||||||
|
|
||||||
// Report an error if no one registered a handoff function before calling this.
|
// Report an error if no one registered a handoff function before calling this.
|
||||||
RETURN_HR_IF_NULL(E_NOT_VALID_STATE, localPfnHandoff);
|
THROW_HR_IF_NULL(E_NOT_VALID_STATE, localPfnHandoff);
|
||||||
|
|
||||||
// Duplicate the handles from what we received.
|
// Duplicate the handles from what we received.
|
||||||
// The contract with COM specifies that any HANDLEs we receive from the caller belong
|
// The contract with COM specifies that any HANDLEs we receive from the caller belong
|
||||||
// to the caller and will be freed when we leave the scope of this method.
|
// to the caller and will be freed when we leave the scope of this method.
|
||||||
// Making our own duplicate copy ensures they hang around in our lifetime.
|
// Making our own duplicate copy ensures they hang around in our lifetime.
|
||||||
RETURN_IF_FAILED(_duplicateHandle(in, in));
|
THROW_IF_FAILED(_duplicateHandle(in, in));
|
||||||
RETURN_IF_FAILED(_duplicateHandle(out, out));
|
THROW_IF_FAILED(_duplicateHandle(out, out));
|
||||||
RETURN_IF_FAILED(_duplicateHandle(signal, signal));
|
THROW_IF_FAILED(_duplicateHandle(signal, signal));
|
||||||
RETURN_IF_FAILED(_duplicateHandle(ref, ref));
|
THROW_IF_FAILED(_duplicateHandle(ref, ref));
|
||||||
RETURN_IF_FAILED(_duplicateHandle(server, server));
|
THROW_IF_FAILED(_duplicateHandle(server, server));
|
||||||
RETURN_IF_FAILED(_duplicateHandle(client, client));
|
THROW_IF_FAILED(_duplicateHandle(client, client));
|
||||||
|
|
||||||
// Call registered handler from when we started listening.
|
// Call registered handler from when we started listening.
|
||||||
return localPfnHandoff(in, out, signal, ref, server, client);
|
THROW_IF_FAILED(localPfnHandoff(in, out, signal, ref, server, client));
|
||||||
|
|
||||||
|
#pragma warning(suppress : 26477)
|
||||||
|
TraceLoggingWrite(
|
||||||
|
g_hTerminalConnectionProvider,
|
||||||
|
"ReceiveTerminalHandoff_Success",
|
||||||
|
TraceLoggingDescription("successfully received a terminal handoff"),
|
||||||
|
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
|
||||||
|
TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
const auto hr = wil::ResultFromCaughtException();
|
||||||
|
|
||||||
|
#pragma warning(suppress : 26477)
|
||||||
|
TraceLoggingWrite(
|
||||||
|
g_hTerminalConnectionProvider,
|
||||||
|
"ReceiveTerminalHandoff_Failed",
|
||||||
|
TraceLoggingDescription("failed while receiving a terminal handoff"),
|
||||||
|
TraceLoggingHResult(hr),
|
||||||
|
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
|
||||||
|
TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
// Copyright (c) Microsoft Corporation.
|
// Copyright (c) Microsoft Corporation.
|
||||||
// Licensed under the MIT license.
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
|
|
||||||
#include "ConptyConnection.h"
|
#include "ConptyConnection.h"
|
||||||
|
|
||||||
#include <windows.h>
|
#include <UserEnv.h>
|
||||||
#include <userenv.h>
|
#include <winternl.h>
|
||||||
|
|
||||||
#include "ConptyConnection.g.cpp"
|
#include "ConptyConnection.g.cpp"
|
||||||
#include "CTerminalHandoff.h"
|
#include "CTerminalHandoff.h"
|
||||||
|
@ -276,24 +276,18 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||||
const HANDLE hClientProcess) :
|
const HANDLE hClientProcess) :
|
||||||
_initialRows{ 25 },
|
_initialRows{ 25 },
|
||||||
_initialCols{ 80 },
|
_initialCols{ 80 },
|
||||||
_commandline{ L"" },
|
_guid{ Utils::CreateGuid() },
|
||||||
_startingDirectory{ L"" },
|
|
||||||
_startingTitle{ L"" },
|
|
||||||
_environment{ nullptr },
|
|
||||||
_guid{},
|
|
||||||
_u8State{},
|
|
||||||
_u16Str{},
|
|
||||||
_buffer{},
|
|
||||||
_inPipe{ hIn },
|
_inPipe{ hIn },
|
||||||
_outPipe{ hOut }
|
_outPipe{ hOut }
|
||||||
{
|
{
|
||||||
THROW_IF_FAILED(ConptyPackPseudoConsole(hServerProcess, hRef, hSig, &_hPC));
|
THROW_IF_FAILED(ConptyPackPseudoConsole(hServerProcess, hRef, hSig, &_hPC));
|
||||||
if (_guid == guid{})
|
|
||||||
{
|
|
||||||
_guid = Utils::CreateGuid();
|
|
||||||
}
|
|
||||||
|
|
||||||
_piClient.hProcess = hClientProcess;
|
_piClient.hProcess = hClientProcess;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_commandline = _commandlineFromProcess(hClientProcess);
|
||||||
|
}
|
||||||
|
CATCH_LOG()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function Description:
|
// Function Description:
|
||||||
|
@ -355,6 +349,11 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||||
return _guid;
|
return _guid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
winrt::hstring ConptyConnection::Commandline() const
|
||||||
|
{
|
||||||
|
return _commandline;
|
||||||
|
}
|
||||||
|
|
||||||
void ConptyConnection::Start()
|
void ConptyConnection::Start()
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -560,6 +559,38 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||||
}
|
}
|
||||||
CATCH_LOG()
|
CATCH_LOG()
|
||||||
|
|
||||||
|
// Returns the command line of the given process.
|
||||||
|
// Requires PROCESS_BASIC_INFORMATION | PROCESS_VM_READ privileges.
|
||||||
|
winrt::hstring ConptyConnection::_commandlineFromProcess(HANDLE process)
|
||||||
|
{
|
||||||
|
struct PROCESS_BASIC_INFORMATION
|
||||||
|
{
|
||||||
|
NTSTATUS ExitStatus;
|
||||||
|
PPEB PebBaseAddress;
|
||||||
|
ULONG_PTR AffinityMask;
|
||||||
|
KPRIORITY BasePriority;
|
||||||
|
ULONG_PTR UniqueProcessId;
|
||||||
|
ULONG_PTR InheritedFromUniqueProcessId;
|
||||||
|
} info;
|
||||||
|
THROW_IF_NTSTATUS_FAILED(NtQueryInformationProcess(process, ProcessBasicInformation, &info, sizeof(info), nullptr));
|
||||||
|
|
||||||
|
// PEB: Process Environment Block
|
||||||
|
// This is a funny structure allocated by the kernel which contains all sorts of useful
|
||||||
|
// information, only a tiny fraction of which are documented publicly unfortunately.
|
||||||
|
// Fortunately however it contains a copy of the command line the process launched with.
|
||||||
|
PEB peb;
|
||||||
|
THROW_IF_WIN32_BOOL_FALSE(ReadProcessMemory(process, info.PebBaseAddress, &peb, sizeof(peb), nullptr));
|
||||||
|
|
||||||
|
RTL_USER_PROCESS_PARAMETERS params;
|
||||||
|
THROW_IF_WIN32_BOOL_FALSE(ReadProcessMemory(process, peb.ProcessParameters, ¶ms, sizeof(params), nullptr));
|
||||||
|
|
||||||
|
// Yeah I know... Don't use "impl" stuff... But why do you make something _that_ useful private? :(
|
||||||
|
// The hstring_builder allows us to create a hstring without intermediate copies. Neat!
|
||||||
|
winrt::impl::hstring_builder commandline{ params.CommandLine.Length / 2u };
|
||||||
|
THROW_IF_WIN32_BOOL_FALSE(ReadProcessMemory(process, params.CommandLine.Buffer, commandline.data(), params.CommandLine.Length, nullptr));
|
||||||
|
return commandline.to_hstring();
|
||||||
|
}
|
||||||
|
|
||||||
DWORD ConptyConnection::_OutputThread()
|
DWORD ConptyConnection::_OutputThread()
|
||||||
{
|
{
|
||||||
// Keep us alive until the output thread terminates; the destructor
|
// Keep us alive until the output thread terminates; the destructor
|
||||||
|
@ -636,8 +667,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||||
HRESULT ConptyConnection::NewHandoff(HANDLE in, HANDLE out, HANDLE signal, HANDLE ref, HANDLE server, HANDLE client) noexcept
|
HRESULT ConptyConnection::NewHandoff(HANDLE in, HANDLE out, HANDLE signal, HANDLE ref, HANDLE server, HANDLE client) noexcept
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
auto conn = winrt::make<implementation::ConptyConnection>(signal, in, out, ref, server, client);
|
_newConnectionHandlers(winrt::make<ConptyConnection>(signal, in, out, ref, server, client));
|
||||||
_newConnectionHandlers(conn);
|
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||||
void ClearBuffer();
|
void ClearBuffer();
|
||||||
|
|
||||||
winrt::guid Guid() const noexcept;
|
winrt::guid Guid() const noexcept;
|
||||||
|
winrt::hstring Commandline() const;
|
||||||
|
|
||||||
static void StartInboundListener();
|
static void StartInboundListener();
|
||||||
static void StopInboundListener();
|
static void StopInboundListener();
|
||||||
|
@ -56,12 +57,13 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||||
WINRT_CALLBACK(TerminalOutput, TerminalOutputHandler);
|
WINRT_CALLBACK(TerminalOutput, TerminalOutputHandler);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static HRESULT NewHandoff(HANDLE in, HANDLE out, HANDLE signal, HANDLE ref, HANDLE server, HANDLE client) noexcept;
|
||||||
|
static winrt::hstring _commandlineFromProcess(HANDLE process);
|
||||||
|
|
||||||
HRESULT _LaunchAttachedClient() noexcept;
|
HRESULT _LaunchAttachedClient() noexcept;
|
||||||
void _indicateExitWithStatus(unsigned int status) noexcept;
|
void _indicateExitWithStatus(unsigned int status) noexcept;
|
||||||
void _ClientTerminated() noexcept;
|
void _ClientTerminated() noexcept;
|
||||||
|
|
||||||
static HRESULT NewHandoff(HANDLE in, HANDLE out, HANDLE signal, HANDLE ref, HANDLE server, HANDLE client) noexcept;
|
|
||||||
|
|
||||||
uint32_t _initialRows{};
|
uint32_t _initialRows{};
|
||||||
uint32_t _initialCols{};
|
uint32_t _initialCols{};
|
||||||
hstring _commandline{};
|
hstring _commandline{};
|
||||||
|
|
|
@ -5,10 +5,13 @@ import "ITerminalConnection.idl";
|
||||||
|
|
||||||
namespace Microsoft.Terminal.TerminalConnection
|
namespace Microsoft.Terminal.TerminalConnection
|
||||||
{
|
{
|
||||||
|
delegate void NewConnectionHandler(ConptyConnection connection);
|
||||||
|
|
||||||
[default_interface] runtimeclass ConptyConnection : ITerminalConnection
|
[default_interface] runtimeclass ConptyConnection : ITerminalConnection
|
||||||
{
|
{
|
||||||
ConptyConnection();
|
ConptyConnection();
|
||||||
Guid Guid { get; };
|
Guid Guid { get; };
|
||||||
|
String Commandline { get; };
|
||||||
void ClearBuffer();
|
void ClearBuffer();
|
||||||
|
|
||||||
static event NewConnectionHandler NewConnection;
|
static event NewConnectionHandler NewConnection;
|
||||||
|
|
|
@ -29,6 +29,4 @@ namespace Microsoft.Terminal.TerminalConnection
|
||||||
event Windows.Foundation.TypedEventHandler<ITerminalConnection, Object> StateChanged;
|
event Windows.Foundation.TypedEventHandler<ITerminalConnection, Object> StateChanged;
|
||||||
ConnectionState State { get; };
|
ConnectionState State { get; };
|
||||||
};
|
};
|
||||||
|
|
||||||
delegate void NewConnectionHandler(ITerminalConnection connection);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -274,10 +274,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
_updateAntiAliasingMode(_renderEngine.get());
|
_updateAntiAliasingMode(_renderEngine.get());
|
||||||
|
|
||||||
// GH#5098: Inform the engine of the opacity of the default text background.
|
// GH#5098: Inform the engine of the opacity of the default text background.
|
||||||
if (_settings.UseAcrylic())
|
// GH#11315: Always do this, even if they don't have acrylic on.
|
||||||
{
|
_renderEngine->SetDefaultTextBackgroundOpacity(::base::saturated_cast<float>(_settings.Opacity()));
|
||||||
_renderEngine->SetDefaultTextBackgroundOpacity(::base::saturated_cast<float>(_settings.Opacity()));
|
|
||||||
}
|
|
||||||
|
|
||||||
THROW_IF_FAILED(_renderEngine->Enable());
|
THROW_IF_FAILED(_renderEngine->Enable());
|
||||||
|
|
||||||
|
@ -444,6 +442,17 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
|
|
||||||
Opacity(newOpacity);
|
Opacity(newOpacity);
|
||||||
|
|
||||||
|
// GH#11285 - If the user is on Windows 10, and they changed the
|
||||||
|
// transparency of the control s.t. it should be partially opaque, then
|
||||||
|
// opt them in to acrylic. It's the only way to have transparency on
|
||||||
|
// Windows 10.
|
||||||
|
// We'll also turn the acrylic back off when they're fully opaque, which
|
||||||
|
// is what the Terminal did prior to 1.12.
|
||||||
|
if (!IsVintageOpacityAvailable())
|
||||||
|
{
|
||||||
|
_settings.UseAcrylic(newOpacity < 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
auto eventArgs = winrt::make_self<TransparencyChangedEventArgs>(newOpacity);
|
auto eventArgs = winrt::make_self<TransparencyChangedEventArgs>(newOpacity);
|
||||||
_TransparencyChangedHandlers(*this, *eventArgs);
|
_TransparencyChangedHandlers(*this, *eventArgs);
|
||||||
}
|
}
|
||||||
|
@ -469,6 +478,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
{
|
{
|
||||||
_renderEngine->ToggleShaderEffects();
|
_renderEngine->ToggleShaderEffects();
|
||||||
}
|
}
|
||||||
|
// Always redraw after toggling effects. This way even if the control
|
||||||
|
// does not have focus it will update immediately.
|
||||||
|
_renderer->TriggerRedrawAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
|
@ -570,6 +582,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
_settings = settings;
|
_settings = settings;
|
||||||
|
|
||||||
_runtimeOpacity = std::nullopt;
|
_runtimeOpacity = std::nullopt;
|
||||||
|
_runtimeUseAcrylic = std::nullopt;
|
||||||
|
|
||||||
|
// GH#11285 - If the user is on Windows 10, and they wanted opacity, but
|
||||||
|
// didn't explicitly request acrylic, then opt them in to acrylic.
|
||||||
|
// On Windows 11+, this isn't needed, because we can have vintage opacity.
|
||||||
|
if (!IsVintageOpacityAvailable() && _settings.Opacity() < 1.0 && !_settings.UseAcrylic())
|
||||||
|
{
|
||||||
|
_runtimeUseAcrylic = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize our font information.
|
// Initialize our font information.
|
||||||
const auto fontFace = _settings.FontFace();
|
const auto fontFace = _settings.FontFace();
|
||||||
|
@ -1026,7 +1047,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
|
|
||||||
TerminalConnection::ConnectionState ControlCore::ConnectionState() const
|
TerminalConnection::ConnectionState ControlCore::ConnectionState() const
|
||||||
{
|
{
|
||||||
return _connection.State();
|
return _connection ? _connection.State() : TerminalConnection::ConnectionState::Closed;
|
||||||
}
|
}
|
||||||
|
|
||||||
hstring ControlCore::Title()
|
hstring ControlCore::Title()
|
||||||
|
@ -1546,4 +1567,20 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
|
|
||||||
return hstring(ss.str());
|
return hstring(ss.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Helper to check if we're on Windows 11 or not. This is used to check if
|
||||||
|
// we need to use acrylic to achieve transparency, because vintage opacity
|
||||||
|
// doesn't work in islands on win10.
|
||||||
|
// Remove when we can remove the rest of GH#11285
|
||||||
|
bool ControlCore::IsVintageOpacityAvailable() noexcept
|
||||||
|
{
|
||||||
|
OSVERSIONINFOEXW osver{};
|
||||||
|
osver.dwOSVersionInfoSize = sizeof(osver);
|
||||||
|
osver.dwBuildNumber = 22000;
|
||||||
|
|
||||||
|
DWORDLONG dwlConditionMask = 0;
|
||||||
|
VER_SET_CONDITION(dwlConditionMask, VER_BUILDNUMBER, VER_GREATER_EQUAL);
|
||||||
|
|
||||||
|
return VerifyVersionInfoW(&osver, VER_BUILDNUMBER, dwlConditionMask) != FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -158,7 +158,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
|
|
||||||
hstring ReadEntireBuffer() const;
|
hstring ReadEntireBuffer() const;
|
||||||
|
|
||||||
|
static bool IsVintageOpacityAvailable() noexcept;
|
||||||
|
|
||||||
RUNTIME_SETTING(double, Opacity, _settings.Opacity());
|
RUNTIME_SETTING(double, Opacity, _settings.Opacity());
|
||||||
|
RUNTIME_SETTING(bool, UseAcrylic, _settings.UseAcrylic());
|
||||||
|
|
||||||
// -------------------------------- WinRT Events ---------------------------------
|
// -------------------------------- WinRT Events ---------------------------------
|
||||||
// clang-format off
|
// clang-format off
|
||||||
|
|
|
@ -43,6 +43,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
{
|
{
|
||||||
_controlPadding = padding;
|
_controlPadding = padding;
|
||||||
}
|
}
|
||||||
|
void InteractivityAutomationPeer::ParentProvider(AutomationPeer parentProvider)
|
||||||
|
{
|
||||||
|
_parentProvider = parentProvider;
|
||||||
|
}
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
// - Signals the ui automation client that the terminal's selection has
|
// - Signals the ui automation client that the terminal's selection has
|
||||||
|
@ -110,30 +114,21 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
// ScreenInfoUiaProvider doesn't actually use parameter, so just pass in nullptr
|
// ScreenInfoUiaProvider doesn't actually use parameter, so just pass in nullptr
|
||||||
THROW_IF_FAILED(_uiaProvider->RangeFromChild(/* IRawElementProviderSimple */ nullptr,
|
THROW_IF_FAILED(_uiaProvider->RangeFromChild(/* IRawElementProviderSimple */ nullptr,
|
||||||
&returnVal));
|
&returnVal));
|
||||||
|
return _CreateXamlUiaTextRange(returnVal);
|
||||||
const auto parentProvider = this->ProviderFromPeer(*this);
|
|
||||||
const auto xutr = winrt::make_self<XamlUiaTextRange>(returnVal, parentProvider);
|
|
||||||
return xutr.as<XamlAutomation::ITextRangeProvider>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
XamlAutomation::ITextRangeProvider InteractivityAutomationPeer::RangeFromPoint(Windows::Foundation::Point screenLocation)
|
XamlAutomation::ITextRangeProvider InteractivityAutomationPeer::RangeFromPoint(Windows::Foundation::Point screenLocation)
|
||||||
{
|
{
|
||||||
UIA::ITextRangeProvider* returnVal;
|
UIA::ITextRangeProvider* returnVal;
|
||||||
THROW_IF_FAILED(_uiaProvider->RangeFromPoint({ screenLocation.X, screenLocation.Y }, &returnVal));
|
THROW_IF_FAILED(_uiaProvider->RangeFromPoint({ screenLocation.X, screenLocation.Y }, &returnVal));
|
||||||
|
return _CreateXamlUiaTextRange(returnVal);
|
||||||
const auto parentProvider = this->ProviderFromPeer(*this);
|
|
||||||
const auto xutr = winrt::make_self<XamlUiaTextRange>(returnVal, parentProvider);
|
|
||||||
return xutr.as<XamlAutomation::ITextRangeProvider>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
XamlAutomation::ITextRangeProvider InteractivityAutomationPeer::DocumentRange()
|
XamlAutomation::ITextRangeProvider InteractivityAutomationPeer::DocumentRange()
|
||||||
{
|
{
|
||||||
UIA::ITextRangeProvider* returnVal;
|
UIA::ITextRangeProvider* returnVal;
|
||||||
THROW_IF_FAILED(_uiaProvider->get_DocumentRange(&returnVal));
|
THROW_IF_FAILED(_uiaProvider->get_DocumentRange(&returnVal));
|
||||||
|
return _CreateXamlUiaTextRange(returnVal);
|
||||||
const auto parentProvider = this->ProviderFromPeer(*this);
|
|
||||||
const auto xutr = winrt::make_self<XamlUiaTextRange>(returnVal, parentProvider);
|
|
||||||
return xutr.as<XamlAutomation::ITextRangeProvider>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
XamlAutomation::SupportedTextSelection InteractivityAutomationPeer::SupportedTextSelection()
|
XamlAutomation::SupportedTextSelection InteractivityAutomationPeer::SupportedTextSelection()
|
||||||
|
@ -180,6 +175,20 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
}
|
}
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
|
XamlAutomation::ITextRangeProvider InteractivityAutomationPeer::_CreateXamlUiaTextRange(UIA::ITextRangeProvider* returnVal) const
|
||||||
|
{
|
||||||
|
// LOAD-BEARING: use _parentProvider->ProviderFromPeer(_parentProvider) instead of this->ProviderFromPeer(*this).
|
||||||
|
// Since we split the automation peer into TermControlAutomationPeer and InteractivityAutomationPeer,
|
||||||
|
// using "this" returns null. This can cause issues with some UIA Client scenarios like any navigation in Narrator.
|
||||||
|
const auto parent{ _parentProvider.get() };
|
||||||
|
if (!parent)
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
const auto xutr = winrt::make_self<XamlUiaTextRange>(returnVal, parent.ProviderFromPeer(parent));
|
||||||
|
return xutr.as<XamlAutomation::ITextRangeProvider>();
|
||||||
|
};
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
// - extracts the UiaTextRanges from the SAFEARRAY and converts them to Xaml ITextRangeProviders
|
// - extracts the UiaTextRanges from the SAFEARRAY and converts them to Xaml ITextRangeProviders
|
||||||
// Arguments:
|
// Arguments:
|
||||||
|
@ -194,11 +203,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
|
|
||||||
std::vector<XamlAutomation::ITextRangeProvider> vec;
|
std::vector<XamlAutomation::ITextRangeProvider> vec;
|
||||||
vec.reserve(count);
|
vec.reserve(count);
|
||||||
auto parentProvider = this->ProviderFromPeer(*this);
|
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
auto xutr = make_self<XamlUiaTextRange>(providers[i].detach(), parentProvider);
|
if (auto xutr = _CreateXamlUiaTextRange(providers[i].detach()))
|
||||||
vec.emplace_back(xutr.as<XamlAutomation::ITextRangeProvider>());
|
{
|
||||||
|
vec.emplace_back(std::move(xutr));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
com_array<XamlAutomation::ITextRangeProvider> result{ vec };
|
com_array<XamlAutomation::ITextRangeProvider> result{ vec };
|
||||||
|
|
|
@ -43,6 +43,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
|
|
||||||
void SetControlBounds(const Windows::Foundation::Rect bounds);
|
void SetControlBounds(const Windows::Foundation::Rect bounds);
|
||||||
void SetControlPadding(const Core::Padding padding);
|
void SetControlPadding(const Core::Padding padding);
|
||||||
|
void ParentProvider(Windows::UI::Xaml::Automation::Peers::AutomationPeer parentProvider);
|
||||||
|
|
||||||
#pragma region IUiaEventDispatcher
|
#pragma region IUiaEventDispatcher
|
||||||
void SignalSelectionChanged() override;
|
void SignalSelectionChanged() override;
|
||||||
|
@ -74,8 +75,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
TYPED_EVENT(CursorChanged, IInspectable, IInspectable);
|
TYPED_EVENT(CursorChanged, IInspectable, IInspectable);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Windows::UI::Xaml::Automation::Provider::ITextRangeProvider _CreateXamlUiaTextRange(::ITextRangeProvider* returnVal) const;
|
||||||
|
|
||||||
::Microsoft::WRL::ComPtr<::Microsoft::Terminal::TermControlUiaProvider> _uiaProvider;
|
::Microsoft::WRL::ComPtr<::Microsoft::Terminal::TermControlUiaProvider> _uiaProvider;
|
||||||
winrt::Microsoft::Terminal::Control::implementation::ControlInteractivity* _interactivity;
|
winrt::Microsoft::Terminal::Control::implementation::ControlInteractivity* _interactivity;
|
||||||
|
weak_ref<Windows::UI::Xaml::Automation::Peers::AutomationPeer> _parentProvider;
|
||||||
|
|
||||||
til::rectangle _controlBounds{};
|
til::rectangle _controlBounds{};
|
||||||
til::rectangle _controlPadding{};
|
til::rectangle _controlPadding{};
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
// Copyright (c) Microsoft Corporation.
|
// Copyright (c) Microsoft Corporation.
|
||||||
// Licensed under the MIT license.
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
namespace Microsoft.Terminal.Control
|
namespace Microsoft.Terminal.Control
|
||||||
{
|
{
|
||||||
[default_interface] runtimeclass InteractivityAutomationPeer :
|
[default_interface] runtimeclass InteractivityAutomationPeer :
|
||||||
|
@ -10,6 +9,7 @@ namespace Microsoft.Terminal.Control
|
||||||
|
|
||||||
void SetControlBounds(Windows.Foundation.Rect bounds);
|
void SetControlBounds(Windows.Foundation.Rect bounds);
|
||||||
void SetControlPadding(Microsoft.Terminal.Core.Padding padding);
|
void SetControlPadding(Microsoft.Terminal.Core.Padding padding);
|
||||||
|
void ParentProvider(Windows.UI.Xaml.Automation.Peers.AutomationPeer parentProvider);
|
||||||
|
|
||||||
event Windows.Foundation.TypedEventHandler<Object, Object> SelectionChanged;
|
event Windows.Foundation.TypedEventHandler<Object, Object> SelectionChanged;
|
||||||
event Windows.Foundation.TypedEventHandler<Object, Object> TextChanged;
|
event Windows.Foundation.TypedEventHandler<Object, Object> TextChanged;
|
||||||
|
|
|
@ -454,7 +454,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
}
|
}
|
||||||
|
|
||||||
// GH#5098: Inform the engine of the new opacity of the default text background.
|
// GH#5098: Inform the engine of the new opacity of the default text background.
|
||||||
_core.SetBackgroundOpacity(::base::saturated_cast<float>(_core.Opacity()));
|
//
|
||||||
|
// TODO! This sure seems contrived, shouldn't the core... already
|
||||||
|
// know this?
|
||||||
|
_core.SetBackgroundOpacity(_core.Opacity());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -45,6 +45,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
_contentAutomationPeer.SelectionChanged([this](auto&&, auto&&) { SignalSelectionChanged(); });
|
_contentAutomationPeer.SelectionChanged([this](auto&&, auto&&) { SignalSelectionChanged(); });
|
||||||
_contentAutomationPeer.TextChanged([this](auto&&, auto&&) { SignalTextChanged(); });
|
_contentAutomationPeer.TextChanged([this](auto&&, auto&&) { SignalTextChanged(); });
|
||||||
_contentAutomationPeer.CursorChanged([this](auto&&, auto&&) { SignalCursorChanged(); });
|
_contentAutomationPeer.CursorChanged([this](auto&&, auto&&) { SignalCursorChanged(); });
|
||||||
|
_contentAutomationPeer.ParentProvider(*this);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
|
@ -226,30 +227,4 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
// Method Description:
|
|
||||||
// - extracts the UiaTextRanges from the SAFEARRAY and converts them to Xaml ITextRangeProviders
|
|
||||||
// Arguments:
|
|
||||||
// - SAFEARRAY of UIA::UiaTextRange (ITextRangeProviders)
|
|
||||||
// Return Value:
|
|
||||||
// - com_array of Xaml Wrapped UiaTextRange (ITextRangeProviders)
|
|
||||||
com_array<XamlAutomation::ITextRangeProvider> TermControlAutomationPeer::WrapArrayOfTextRangeProviders(SAFEARRAY* textRanges)
|
|
||||||
{
|
|
||||||
// transfer ownership of UiaTextRanges to this new vector
|
|
||||||
auto providers = SafeArrayToOwningVector<::Microsoft::Terminal::TermControlUiaTextRange>(textRanges);
|
|
||||||
int count = gsl::narrow<int>(providers.size());
|
|
||||||
|
|
||||||
std::vector<XamlAutomation::ITextRangeProvider> vec;
|
|
||||||
vec.reserve(count);
|
|
||||||
auto parentProvider = this->ProviderFromPeer(*this);
|
|
||||||
for (int i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
auto xutr = make_self<XamlUiaTextRange>(providers[i].detach(), parentProvider);
|
|
||||||
vec.emplace_back(xutr.as<XamlAutomation::ITextRangeProvider>());
|
|
||||||
}
|
|
||||||
|
|
||||||
com_array<XamlAutomation::ITextRangeProvider> result{ vec };
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,7 +78,5 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
private:
|
private:
|
||||||
winrt::Microsoft::Terminal::Control::implementation::TermControl* _termControl;
|
winrt::Microsoft::Terminal::Control::implementation::TermControl* _termControl;
|
||||||
Control::InteractivityAutomationPeer _contentAutomationPeer;
|
Control::InteractivityAutomationPeer _contentAutomationPeer;
|
||||||
|
|
||||||
winrt::com_array<Windows::UI::Xaml::Automation::Provider::ITextRangeProvider> WrapArrayOfTextRangeProviders(SAFEARRAY* textRanges);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "../types/TermControlUiaTextRange.hpp"
|
#include "../types/TermControlUiaTextRange.hpp"
|
||||||
#include <UIAutomationClient.h>
|
#include <UIAutomationClient.h>
|
||||||
#include <UIAutomationCoreApi.h>
|
#include <UIAutomationCoreApi.h>
|
||||||
|
#include "../types/UiaTracing.h"
|
||||||
|
|
||||||
// the same as COR_E_NOTSUPPORTED
|
// the same as COR_E_NOTSUPPORTED
|
||||||
// we don't want to import the CLR headers to get it
|
// we don't want to import the CLR headers to get it
|
||||||
|
@ -182,6 +183,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
|
|
||||||
XamlAutomation::IRawElementProviderSimple XamlUiaTextRange::GetEnclosingElement()
|
XamlAutomation::IRawElementProviderSimple XamlUiaTextRange::GetEnclosingElement()
|
||||||
{
|
{
|
||||||
|
::Microsoft::Console::Types::UiaTracing::TextRange::GetEnclosingElement(*static_cast<::Microsoft::Console::Types::UiaTextRangeBase*>(_uiaProvider.get()));
|
||||||
return _parentProvider;
|
return _parentProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
228
src/cascadia/TerminalCore/ColorFix.cpp
Normal file
228
src/cascadia/TerminalCore/ColorFix.cpp
Normal file
|
@ -0,0 +1,228 @@
|
||||||
|
// Copyright (c) Microsoft Corporation.
|
||||||
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
// A lot of code was taken from
|
||||||
|
// https://github.com/Maximus5/ConEmu/blob/master/src/ConEmu/ColorFix.cpp
|
||||||
|
// and then adjusted to fit our style guidelines
|
||||||
|
|
||||||
|
#include "pch.h"
|
||||||
|
|
||||||
|
#include <Windows.h>
|
||||||
|
#include "ColorFix.hpp"
|
||||||
|
|
||||||
|
static constexpr double gMinThreshold = 12.0;
|
||||||
|
static constexpr double gExpThreshold = 20.0;
|
||||||
|
static constexpr double gLStep = 5.0;
|
||||||
|
|
||||||
|
static constexpr double rad006 = 0.104719755119659774;
|
||||||
|
static constexpr double rad025 = 0.436332312998582394;
|
||||||
|
static constexpr double rad030 = 0.523598775598298873;
|
||||||
|
static constexpr double rad060 = 1.047197551196597746;
|
||||||
|
static constexpr double rad063 = 1.099557428756427633;
|
||||||
|
static constexpr double rad180 = 3.141592653589793238;
|
||||||
|
static constexpr double rad275 = 4.799655442984406336;
|
||||||
|
static constexpr double rad360 = 6.283185307179586476;
|
||||||
|
|
||||||
|
ColorFix::ColorFix(COLORREF color)
|
||||||
|
{
|
||||||
|
rgb = color;
|
||||||
|
_ToLab();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method Description:
|
||||||
|
// - Helper function to calculate HPrime
|
||||||
|
double ColorFix::_GetHPrimeFn(double x, double y)
|
||||||
|
{
|
||||||
|
if (x == 0 && y == 0)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto hueAngle = atan2(x, y);
|
||||||
|
return hueAngle >= 0 ? hueAngle : hueAngle + rad360;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method Description:
|
||||||
|
// - Given 2 colors, computes the DeltaE value between them
|
||||||
|
// Arguments:
|
||||||
|
// - x1: the first color
|
||||||
|
// - x2: the second color
|
||||||
|
// Return Value:
|
||||||
|
// - The DeltaE value between x1 and x2
|
||||||
|
double ColorFix::_GetDeltaE(ColorFix x1, ColorFix x2)
|
||||||
|
{
|
||||||
|
constexpr double kSubL = 1;
|
||||||
|
constexpr double kSubC = 1;
|
||||||
|
constexpr double kSubH = 1;
|
||||||
|
|
||||||
|
// Delta L Prime
|
||||||
|
const double deltaLPrime = x2.L - x1.L;
|
||||||
|
|
||||||
|
// L Bar
|
||||||
|
const double lBar = (x1.L + x2.L) / 2;
|
||||||
|
|
||||||
|
// C1 & C2
|
||||||
|
const double c1 = sqrt(pow(x1.A, 2) + pow(x1.B, 2));
|
||||||
|
const double c2 = sqrt(pow(x2.A, 2) + pow(x2.B, 2));
|
||||||
|
|
||||||
|
// C Bar
|
||||||
|
const double cBar = (c1 + c2) / 2;
|
||||||
|
|
||||||
|
// A Prime 1
|
||||||
|
const double aPrime1 = x1.A + (x1.A / 2) * (1 - sqrt(pow(cBar, 7) / (pow(cBar, 7) + pow(25.0, 7))));
|
||||||
|
|
||||||
|
// A Prime 2
|
||||||
|
const double aPrime2 = x2.A + (x2.A / 2) * (1 - sqrt(pow(cBar, 7) / (pow(cBar, 7) + pow(25.0, 7))));
|
||||||
|
|
||||||
|
// C Prime 1
|
||||||
|
const double cPrime1 = sqrt(pow(aPrime1, 2) + pow(x1.B, 2));
|
||||||
|
|
||||||
|
// C Prime 2
|
||||||
|
const double cPrime2 = sqrt(pow(aPrime2, 2) + pow(x2.B, 2));
|
||||||
|
|
||||||
|
// C Bar Prime
|
||||||
|
const double cBarPrime = (cPrime1 + cPrime2) / 2;
|
||||||
|
|
||||||
|
// Delta C Prime
|
||||||
|
const double deltaCPrime = cPrime2 - cPrime1;
|
||||||
|
|
||||||
|
// S sub L
|
||||||
|
const double sSubL = 1 + ((0.015 * pow(lBar - 50, 2)) / sqrt(20 + pow(lBar - 50, 2)));
|
||||||
|
|
||||||
|
// S sub C
|
||||||
|
const double sSubC = 1 + 0.045 * cBarPrime;
|
||||||
|
|
||||||
|
// h Prime 1
|
||||||
|
const double hPrime1 = _GetHPrimeFn(x1.B, aPrime1);
|
||||||
|
|
||||||
|
// h Prime 2
|
||||||
|
const double hPrime2 = _GetHPrimeFn(x2.B, aPrime2);
|
||||||
|
|
||||||
|
// Delta H Prime
|
||||||
|
const double deltaHPrime = 0 == c1 || 0 == c2 ? 0 : 2 * sqrt(cPrime1 * cPrime2) * sin(abs(hPrime1 - hPrime2) <= rad180 ? hPrime2 - hPrime1 : (hPrime2 <= hPrime1 ? hPrime2 - hPrime1 + rad360 : hPrime2 - hPrime1 - rad360) / 2);
|
||||||
|
|
||||||
|
// H Bar Prime
|
||||||
|
const double hBarPrime = (abs(hPrime1 - hPrime2) > rad180) ? (hPrime1 + hPrime2 + rad360) / 2 : (hPrime1 + hPrime2) / 2;
|
||||||
|
|
||||||
|
// T
|
||||||
|
const double t = 1 - 0.17 * cos(hBarPrime - rad030) + 0.24 * cos(2 * hBarPrime) + 0.32 * cos(3 * hBarPrime + rad006) - 0.20 * cos(4 * hBarPrime - rad063);
|
||||||
|
|
||||||
|
// S sub H
|
||||||
|
const double sSubH = 1 + 0.015 * cBarPrime * t;
|
||||||
|
|
||||||
|
// R sub T
|
||||||
|
const double rSubT = -2 * sqrt(pow(cBarPrime, 7) / (pow(cBarPrime, 7) + pow(25.0, 7))) * sin(rad060 * exp(-pow((hBarPrime - rad275) / rad025, 2)));
|
||||||
|
|
||||||
|
// Put it all together!
|
||||||
|
const double lightness = deltaLPrime / (kSubL * sSubL);
|
||||||
|
const double chroma = deltaCPrime / (kSubC * sSubC);
|
||||||
|
const double hue = deltaHPrime / (kSubH * sSubH);
|
||||||
|
|
||||||
|
return sqrt(pow(lightness, 2) + pow(chroma, 2) + pow(hue, 2) + rSubT * chroma * hue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method Description:
|
||||||
|
// - Populates our L, A, B values, based on our r, g, b values
|
||||||
|
// - Converts a color in rgb format to a color in lab format
|
||||||
|
// - Reference: http://www.easyrgb.com/index.php?X=MATH&H=01#text1
|
||||||
|
void ColorFix::_ToLab()
|
||||||
|
{
|
||||||
|
double var_R = r / 255.0;
|
||||||
|
double var_G = g / 255.0;
|
||||||
|
double var_B = b / 255.0;
|
||||||
|
|
||||||
|
var_R = var_R > 0.04045 ? pow(((var_R + 0.055) / 1.055), 2.4) : var_R / 12.92;
|
||||||
|
var_G = var_G > 0.04045 ? pow(((var_G + 0.055) / 1.055), 2.4) : var_G / 12.92;
|
||||||
|
var_B = var_B > 0.04045 ? pow(((var_B + 0.055) / 1.055), 2.4) : var_B / 12.92;
|
||||||
|
|
||||||
|
var_R = var_R * 100.;
|
||||||
|
var_G = var_G * 100.;
|
||||||
|
var_B = var_B * 100.;
|
||||||
|
|
||||||
|
//Observer. = 2 degrees, Illuminant = D65
|
||||||
|
const double X = var_R * 0.4124 + var_G * 0.3576 + var_B * 0.1805;
|
||||||
|
const double Y = var_R * 0.2126 + var_G * 0.7152 + var_B * 0.0722;
|
||||||
|
const double Z = var_R * 0.0193 + var_G * 0.1192 + var_B * 0.9505;
|
||||||
|
|
||||||
|
double var_X = X / 95.047; //ref_X = 95.047 (Observer= 2 degrees, Illuminant= D65)
|
||||||
|
double var_Y = Y / 100.000; //ref_Y = 100.000
|
||||||
|
double var_Z = Z / 108.883; //ref_Z = 108.883
|
||||||
|
|
||||||
|
var_X = var_X > 0.008856 ? pow(var_X, (1. / 3.)) : (7.787 * var_X) + (16. / 116.);
|
||||||
|
var_Y = var_Y > 0.008856 ? pow(var_Y, (1. / 3.)) : (7.787 * var_Y) + (16. / 116.);
|
||||||
|
var_Z = var_Z > 0.008856 ? pow(var_Z, (1. / 3.)) : (7.787 * var_Z) + (16. / 116.);
|
||||||
|
|
||||||
|
L = (116. * var_Y) - 16.;
|
||||||
|
A = 500. * (var_X - var_Y);
|
||||||
|
B = 200. * (var_Y - var_Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method Description:
|
||||||
|
// - Populates our r, g, b values, based on our L, A, B values
|
||||||
|
// - Converts a color in lab format to a color in rgb format
|
||||||
|
// - Reference: http://www.easyrgb.com/index.php?X=MATH&H=01#text1
|
||||||
|
void ColorFix::_ToRGB()
|
||||||
|
{
|
||||||
|
double var_Y = (L + 16.) / 116.;
|
||||||
|
double var_X = A / 500. + var_Y;
|
||||||
|
double var_Z = var_Y - B / 200.;
|
||||||
|
|
||||||
|
var_Y = (pow(var_Y, 3) > 0.008856) ? pow(var_Y, 3) : (var_Y - 16. / 116.) / 7.787;
|
||||||
|
var_X = (pow(var_X, 3) > 0.008856) ? pow(var_X, 3) : (var_X - 16. / 116.) / 7.787;
|
||||||
|
var_Z = (pow(var_Z, 3) > 0.008856) ? pow(var_Z, 3) : (var_Z - 16. / 116.) / 7.787;
|
||||||
|
|
||||||
|
double X = 95.047 * var_X; //ref_X = 95.047 (Observer= 2 degrees, Illuminant= D65)
|
||||||
|
double Y = 100.000 * var_Y; //ref_Y = 100.000
|
||||||
|
double Z = 108.883 * var_Z; //ref_Z = 108.883
|
||||||
|
|
||||||
|
var_X = X / 100.; //X from 0 to 95.047 (Observer = 2 degrees, Illuminant = D65)
|
||||||
|
var_Y = Y / 100.; //Y from 0 to 100.000
|
||||||
|
var_Z = Z / 100.; //Z from 0 to 108.883
|
||||||
|
|
||||||
|
double var_R = var_X * 3.2406 + var_Y * -1.5372 + var_Z * -0.4986;
|
||||||
|
double var_G = var_X * -0.9689 + var_Y * 1.8758 + var_Z * 0.0415;
|
||||||
|
double var_B = var_X * 0.0557 + var_Y * -0.2040 + var_Z * 1.0570;
|
||||||
|
|
||||||
|
var_R = var_R > 0.0031308 ? 1.055 * pow(var_R, (1 / 2.4)) - 0.055 : var_R = 12.92 * var_R;
|
||||||
|
var_G = var_G > 0.0031308 ? 1.055 * pow(var_G, (1 / 2.4)) - 0.055 : var_G = 12.92 * var_G;
|
||||||
|
var_B = var_B > 0.0031308 ? 1.055 * pow(var_B, (1 / 2.4)) - 0.055 : var_B = 12.92 * var_B;
|
||||||
|
|
||||||
|
r = (BYTE)std::clamp(var_R * 255., 0., 255.);
|
||||||
|
g = (BYTE)std::clamp(var_G * 255., 0., 255.);
|
||||||
|
b = (BYTE)std::clamp(var_B * 255., 0., 255.);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method Description:
|
||||||
|
// - Given foreground and background colors, change the foreground color to
|
||||||
|
// make it more perceivable if necessary
|
||||||
|
// - Arguments:
|
||||||
|
// - fg: the foreground color
|
||||||
|
// - bg: the background color
|
||||||
|
// - Return Value:
|
||||||
|
// - The foreground color after performing any necessary changes to make it more perceivable
|
||||||
|
COLORREF ColorFix::GetPerceivableColor(COLORREF fg, COLORREF bg)
|
||||||
|
{
|
||||||
|
ColorFix backLab(bg);
|
||||||
|
ColorFix frontLab(fg);
|
||||||
|
const double de1 = _GetDeltaE(frontLab, backLab);
|
||||||
|
if (de1 < gMinThreshold)
|
||||||
|
{
|
||||||
|
for (int i = 0; i <= 1; i++)
|
||||||
|
{
|
||||||
|
const double step = (i == 0) ? gLStep : -gLStep;
|
||||||
|
frontLab.L += step;
|
||||||
|
|
||||||
|
while (((i == 0) && (frontLab.L <= 100)) || ((i == 1) && (frontLab.L >= 0)))
|
||||||
|
{
|
||||||
|
const double de2 = _GetDeltaE(frontLab, backLab);
|
||||||
|
if (de2 >= gExpThreshold)
|
||||||
|
{
|
||||||
|
frontLab._ToRGB();
|
||||||
|
return frontLab.rgb;
|
||||||
|
}
|
||||||
|
frontLab.L += step;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return frontLab.rgb;
|
||||||
|
}
|
49
src/cascadia/TerminalCore/ColorFix.hpp
Normal file
49
src/cascadia/TerminalCore/ColorFix.hpp
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
/*++
|
||||||
|
Copyright (c) Microsoft Corporation
|
||||||
|
Licensed under the MIT license.
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
- ColorFix
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
- Implementation of perceptual color nudging, which allows the Terminal
|
||||||
|
to slightly shift the foreground color to make it more perceivable on
|
||||||
|
the current background (for cases where the foreground is very close
|
||||||
|
to being imperceivable on the background).
|
||||||
|
|
||||||
|
Author(s):
|
||||||
|
- Pankaj Bhojwani - Sep 2021
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
struct ColorFix
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ColorFix(COLORREF color);
|
||||||
|
|
||||||
|
static COLORREF GetPerceivableColor(COLORREF fg, COLORREF bg);
|
||||||
|
|
||||||
|
// RGB
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
BYTE r, g, b, dummy;
|
||||||
|
};
|
||||||
|
COLORREF rgb;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Lab
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
double L, A, B;
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
static double _GetHPrimeFn(double x, double y);
|
||||||
|
static double _GetDeltaE(ColorFix x1, ColorFix x2);
|
||||||
|
void _ToLab();
|
||||||
|
void _ToRGB();
|
||||||
|
};
|
|
@ -67,5 +67,6 @@ namespace Microsoft.Terminal.Core
|
||||||
CursorStyle CursorShape;
|
CursorStyle CursorShape;
|
||||||
UInt32 CursorHeight;
|
UInt32 CursorHeight;
|
||||||
Boolean IntenseIsBright;
|
Boolean IntenseIsBright;
|
||||||
|
Boolean AdjustIndistinguishableColors;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,8 @@ Terminal::Terminal() :
|
||||||
_taskbarState{ 0 },
|
_taskbarState{ 0 },
|
||||||
_taskbarProgress{ 0 },
|
_taskbarProgress{ 0 },
|
||||||
_trimBlockSelection{ false },
|
_trimBlockSelection{ false },
|
||||||
_intenseIsBright{ true }
|
_intenseIsBright{ true },
|
||||||
|
_adjustIndistinguishableColors{ true }
|
||||||
{
|
{
|
||||||
auto dispatch = std::make_unique<TerminalDispatch>(*this);
|
auto dispatch = std::make_unique<TerminalDispatch>(*this);
|
||||||
auto engine = std::make_unique<OutputStateMachineEngine>(std::move(dispatch));
|
auto engine = std::make_unique<OutputStateMachineEngine>(std::move(dispatch));
|
||||||
|
@ -175,11 +176,16 @@ void Terminal::UpdateAppearance(const ICoreAppearance& appearance)
|
||||||
_defaultBg = newBackgroundColor.with_alpha(0);
|
_defaultBg = newBackgroundColor.with_alpha(0);
|
||||||
_defaultFg = appearance.DefaultForeground();
|
_defaultFg = appearance.DefaultForeground();
|
||||||
_intenseIsBright = appearance.IntenseIsBright();
|
_intenseIsBright = appearance.IntenseIsBright();
|
||||||
|
_adjustIndistinguishableColors = appearance.AdjustIndistinguishableColors();
|
||||||
|
|
||||||
for (int i = 0; i < 16; i++)
|
for (int i = 0; i < 16; i++)
|
||||||
{
|
{
|
||||||
_colorTable.at(i) = til::color{ appearance.GetColorTableEntry(i) };
|
_colorTable.at(i) = til::color{ appearance.GetColorTableEntry(i) };
|
||||||
}
|
}
|
||||||
|
if (_adjustIndistinguishableColors)
|
||||||
|
{
|
||||||
|
_MakeAdjustedColorArray();
|
||||||
|
}
|
||||||
|
|
||||||
CursorType cursorShape = CursorType::VerticalBar;
|
CursorType cursorShape = CursorType::VerticalBar;
|
||||||
switch (appearance.CursorShape())
|
switch (appearance.CursorShape())
|
||||||
|
@ -849,7 +855,13 @@ WORD Terminal::_TakeVirtualKeyFromLastKeyEvent(const WORD scanCode) noexcept
|
||||||
// will release this lock when it's destructed.
|
// will release this lock when it's destructed.
|
||||||
[[nodiscard]] std::unique_lock<til::ticket_lock> Terminal::LockForReading()
|
[[nodiscard]] std::unique_lock<til::ticket_lock> Terminal::LockForReading()
|
||||||
{
|
{
|
||||||
|
#ifdef NDEBUG
|
||||||
return std::unique_lock{ _readWriteLock };
|
return std::unique_lock{ _readWriteLock };
|
||||||
|
#else
|
||||||
|
auto lock = std::unique_lock{ _readWriteLock };
|
||||||
|
_lastLocker = GetCurrentThreadId();
|
||||||
|
return lock;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
|
@ -859,7 +871,13 @@ WORD Terminal::_TakeVirtualKeyFromLastKeyEvent(const WORD scanCode) noexcept
|
||||||
// will release this lock when it's destructed.
|
// will release this lock when it's destructed.
|
||||||
[[nodiscard]] std::unique_lock<til::ticket_lock> Terminal::LockForWriting()
|
[[nodiscard]] std::unique_lock<til::ticket_lock> Terminal::LockForWriting()
|
||||||
{
|
{
|
||||||
|
#ifdef NDEBUG
|
||||||
return std::unique_lock{ _readWriteLock };
|
return std::unique_lock{ _readWriteLock };
|
||||||
|
#else
|
||||||
|
auto lock = std::unique_lock{ _readWriteLock };
|
||||||
|
_lastLocker = GetCurrentThreadId();
|
||||||
|
return lock;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
Viewport Terminal::_GetMutableViewport() const noexcept
|
Viewport Terminal::_GetMutableViewport() const noexcept
|
||||||
|
|
|
@ -199,6 +199,7 @@ public:
|
||||||
const COORD GetSelectionEnd() const noexcept override;
|
const COORD GetSelectionEnd() const noexcept override;
|
||||||
const std::wstring_view GetConsoleTitle() const noexcept override;
|
const std::wstring_view GetConsoleTitle() const noexcept override;
|
||||||
void ColorSelection(const COORD coordSelectionStart, const COORD coordSelectionEnd, const TextAttribute) override;
|
void ColorSelection(const COORD coordSelectionStart, const COORD coordSelectionEnd, const TextAttribute) override;
|
||||||
|
const bool IsUiaDataInitialized() const noexcept override;
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
void SetWriteInputCallback(std::function<void(std::wstring&)> pfn) noexcept;
|
void SetWriteInputCallback(std::function<void(std::wstring&)> pfn) noexcept;
|
||||||
|
@ -268,6 +269,9 @@ private:
|
||||||
// But we can abuse the fact that the surrounding members rarely change and are huge
|
// But we can abuse the fact that the surrounding members rarely change and are huge
|
||||||
// (std::function is like 64 bytes) to create some natural padding without wasting space.
|
// (std::function is like 64 bytes) to create some natural padding without wasting space.
|
||||||
til::ticket_lock _readWriteLock;
|
til::ticket_lock _readWriteLock;
|
||||||
|
#ifndef NDEBUG
|
||||||
|
DWORD _lastLocker;
|
||||||
|
#endif
|
||||||
|
|
||||||
std::function<void(const int, const int, const int)> _pfnScrollPositionChanged;
|
std::function<void(const int, const int, const int)> _pfnScrollPositionChanged;
|
||||||
std::function<void(const til::color)> _pfnBackgroundColorChanged;
|
std::function<void(const til::color)> _pfnBackgroundColorChanged;
|
||||||
|
@ -297,6 +301,7 @@ private:
|
||||||
bool _bracketedPasteMode;
|
bool _bracketedPasteMode;
|
||||||
bool _trimBlockSelection;
|
bool _trimBlockSelection;
|
||||||
bool _intenseIsBright;
|
bool _intenseIsBright;
|
||||||
|
bool _adjustIndistinguishableColors;
|
||||||
|
|
||||||
size_t _taskbarState;
|
size_t _taskbarState;
|
||||||
size_t _taskbarProgress;
|
size_t _taskbarProgress;
|
||||||
|
@ -397,6 +402,9 @@ private:
|
||||||
|
|
||||||
Microsoft::Console::VirtualTerminal::SgrStack _sgrStack;
|
Microsoft::Console::VirtualTerminal::SgrStack _sgrStack;
|
||||||
|
|
||||||
|
void _MakeAdjustedColorArray();
|
||||||
|
std::array<std::array<COLORREF, 18>, 18> _adjustedForegroundColors;
|
||||||
|
|
||||||
#ifdef UNIT_TESTING
|
#ifdef UNIT_TESTING
|
||||||
friend class TerminalCoreUnitTests::TerminalBufferTests;
|
friend class TerminalCoreUnitTests::TerminalBufferTests;
|
||||||
friend class TerminalCoreUnitTests::TerminalApiTest;
|
friend class TerminalCoreUnitTests::TerminalApiTest;
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
<ClCompile Include="..\TerminalSelection.cpp" />
|
<ClCompile Include="..\TerminalSelection.cpp" />
|
||||||
<ClCompile Include="..\TerminalApi.cpp" />
|
<ClCompile Include="..\TerminalApi.cpp" />
|
||||||
<ClCompile Include="..\Terminal.cpp" />
|
<ClCompile Include="..\Terminal.cpp" />
|
||||||
|
<ClCompile Include="..\ColorFix.cpp" />
|
||||||
<ClCompile Include="..\pch.cpp">
|
<ClCompile Include="..\pch.cpp">
|
||||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -19,6 +20,7 @@
|
||||||
<ClInclude Include="..\ITerminalApi.hpp" />
|
<ClInclude Include="..\ITerminalApi.hpp" />
|
||||||
<ClInclude Include="..\pch.h" />
|
<ClInclude Include="..\pch.h" />
|
||||||
<ClInclude Include="..\Terminal.hpp" />
|
<ClInclude Include="..\Terminal.hpp" />
|
||||||
|
<ClInclude Include="..\ColorFix.hpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -3,11 +3,16 @@
|
||||||
|
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "Terminal.hpp"
|
#include "Terminal.hpp"
|
||||||
|
#include "ColorFix.hpp"
|
||||||
#include <DefaultSettings.h>
|
#include <DefaultSettings.h>
|
||||||
|
|
||||||
using namespace Microsoft::Terminal::Core;
|
using namespace Microsoft::Terminal::Core;
|
||||||
using namespace Microsoft::Console::Types;
|
using namespace Microsoft::Console::Types;
|
||||||
using namespace Microsoft::Console::Render;
|
using namespace Microsoft::Console::Render;
|
||||||
|
|
||||||
|
static constexpr size_t DefaultBgIndex{ 16 };
|
||||||
|
static constexpr size_t DefaultFgIndex{ 17 };
|
||||||
|
|
||||||
Viewport Terminal::GetViewport() noexcept
|
Viewport Terminal::GetViewport() noexcept
|
||||||
{
|
{
|
||||||
return _GetVisibleViewport();
|
return _GetVisibleViewport();
|
||||||
|
@ -44,14 +49,47 @@ const TextAttribute Terminal::GetDefaultBrushColors() noexcept
|
||||||
|
|
||||||
std::pair<COLORREF, COLORREF> Terminal::GetAttributeColors(const TextAttribute& attr) const noexcept
|
std::pair<COLORREF, COLORREF> Terminal::GetAttributeColors(const TextAttribute& attr) const noexcept
|
||||||
{
|
{
|
||||||
|
std::pair<COLORREF, COLORREF> colors;
|
||||||
_blinkingState.RecordBlinkingUsage(attr);
|
_blinkingState.RecordBlinkingUsage(attr);
|
||||||
auto colors = attr.CalculateRgbColors(
|
const auto fgTextColor = attr.GetForeground();
|
||||||
_colorTable,
|
const auto bgTextColor = attr.GetBackground();
|
||||||
_defaultFg,
|
|
||||||
_defaultBg,
|
// We want to nudge the foreground color to make it more perceivable only for the
|
||||||
_screenReversed,
|
// default color pairs within the color table
|
||||||
_blinkingState.IsBlinkingFaint(),
|
if (_adjustIndistinguishableColors &&
|
||||||
_intenseIsBright);
|
!(attr.IsFaint() || (attr.IsBlinking() && _blinkingState.IsBlinkingFaint())) &&
|
||||||
|
(fgTextColor.IsDefault() || fgTextColor.IsLegacy()) &&
|
||||||
|
(bgTextColor.IsDefault() || bgTextColor.IsLegacy()))
|
||||||
|
{
|
||||||
|
const auto bgIndex = bgTextColor.IsDefault() ? DefaultBgIndex : bgTextColor.GetIndex();
|
||||||
|
auto fgIndex = fgTextColor.IsDefault() ? DefaultFgIndex : fgTextColor.GetIndex();
|
||||||
|
|
||||||
|
if (fgTextColor.IsIndex16() && (fgIndex < 8) && attr.IsBold() && _intenseIsBright)
|
||||||
|
{
|
||||||
|
// There is a special case for bold here - we need to get the bright version of the foreground color
|
||||||
|
fgIndex += 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attr.IsReverseVideo() ^ _screenReversed)
|
||||||
|
{
|
||||||
|
colors.first = _adjustedForegroundColors[fgIndex][bgIndex];
|
||||||
|
colors.second = fgTextColor.GetColor(_colorTable, _defaultFg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
colors.first = _adjustedForegroundColors[bgIndex][fgIndex];
|
||||||
|
colors.second = bgTextColor.GetColor(_colorTable, _defaultBg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
colors = attr.CalculateRgbColors(_colorTable,
|
||||||
|
_defaultFg,
|
||||||
|
_defaultBg,
|
||||||
|
_screenReversed,
|
||||||
|
_blinkingState.IsBlinkingFaint(),
|
||||||
|
_intenseIsBright);
|
||||||
|
}
|
||||||
colors.first |= 0xff000000;
|
colors.first |= 0xff000000;
|
||||||
// We only care about alpha for the default BG (which enables acrylic)
|
// We only care about alpha for the default BG (which enables acrylic)
|
||||||
// If the bg isn't the default bg color, or reverse video is enabled, make it fully opaque.
|
// If the bg isn't the default bg color, or reverse video is enabled, make it fully opaque.
|
||||||
|
@ -233,6 +271,9 @@ catch (...)
|
||||||
void Terminal::LockConsole() noexcept
|
void Terminal::LockConsole() noexcept
|
||||||
{
|
{
|
||||||
_readWriteLock.lock();
|
_readWriteLock.lock();
|
||||||
|
#ifndef NDEBUG
|
||||||
|
_lastLocker = GetCurrentThreadId();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
|
@ -250,3 +291,43 @@ bool Terminal::IsScreenReversed() const noexcept
|
||||||
{
|
{
|
||||||
return _screenReversed;
|
return _screenReversed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bool Terminal::IsUiaDataInitialized() const noexcept
|
||||||
|
{
|
||||||
|
// GH#11135: Windows Terminal needs to create and return an automation peer
|
||||||
|
// when a screen reader requests it. However, the terminal might not be fully
|
||||||
|
// initialized yet. So we use this to check if any crucial components of
|
||||||
|
// UiaData are not yet initialized.
|
||||||
|
return !!_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method Description:
|
||||||
|
// - Creates the adjusted color array, which contains the possible foreground colors,
|
||||||
|
// adjusted for perceivability
|
||||||
|
// - The adjusted color array is 2-d, and effectively maps a background and foreground
|
||||||
|
// color pair to the adjusted foreground for that color pair
|
||||||
|
void Terminal::_MakeAdjustedColorArray()
|
||||||
|
{
|
||||||
|
// The color table has 16 colors, but the adjusted color table needs to be 18
|
||||||
|
// to include the default background and default foreground colors
|
||||||
|
std::array<COLORREF, 18> colorTableWithDefaults;
|
||||||
|
std::copy_n(std::begin(_colorTable), 16, std::begin(colorTableWithDefaults));
|
||||||
|
colorTableWithDefaults[DefaultBgIndex] = _defaultBg;
|
||||||
|
colorTableWithDefaults[DefaultFgIndex] = _defaultFg;
|
||||||
|
for (auto fgIndex = 0; fgIndex < 18; ++fgIndex)
|
||||||
|
{
|
||||||
|
const auto fg = til::at(colorTableWithDefaults, fgIndex);
|
||||||
|
for (auto bgIndex = 0; bgIndex < 18; ++bgIndex)
|
||||||
|
{
|
||||||
|
if (fgIndex == bgIndex)
|
||||||
|
{
|
||||||
|
_adjustedForegroundColors[bgIndex][fgIndex] = fg;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const auto bg = til::at(colorTableWithDefaults, bgIndex);
|
||||||
|
_adjustedForegroundColors[bgIndex][fgIndex] = ColorFix::GetPerceivableColor(fg, bg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) Microsoft Corporation.
|
// Copyright (c) Microsoft Corporation.
|
||||||
// Licensed under the MIT license.
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
|
@ -369,7 +369,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||||
{
|
{
|
||||||
const auto kbdVM{ get_self<KeyBindingViewModel>(_KeyBindingList.GetAt(i)) };
|
const auto kbdVM{ get_self<KeyBindingViewModel>(_KeyBindingList.GetAt(i)) };
|
||||||
const auto& otherKeys{ kbdVM->CurrentKeys() };
|
const auto& otherKeys{ kbdVM->CurrentKeys() };
|
||||||
if (keys.Modifiers() == otherKeys.Modifiers() && keys.Vkey() == otherKeys.Vkey())
|
if (otherKeys && keys.Modifiers() == otherKeys.Modifiers() && keys.Vkey() == otherKeys.Vkey())
|
||||||
{
|
{
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
<StackPanel Margin="{StaticResource StandardControlMargin}">
|
<StackPanel Margin="{StaticResource StandardControlMargin}">
|
||||||
<local:SettingContainer x:Uid="AddProfile_Duplicate">
|
<local:SettingContainer x:Uid="AddProfile_Duplicate">
|
||||||
<muxc:RadioButtons x:Name="Profiles"
|
<muxc:RadioButtons x:Name="Profiles"
|
||||||
|
AutomationProperties.AccessibilityView="Content"
|
||||||
ItemsSource="{x:Bind State.Settings.AllProfiles, Mode=OneWay}">
|
ItemsSource="{x:Bind State.Settings.AllProfiles, Mode=OneWay}">
|
||||||
<muxc:RadioButtons.ItemTemplate>
|
<muxc:RadioButtons.ItemTemplate>
|
||||||
<DataTemplate x:DataType="model:Profile">
|
<DataTemplate x:DataType="model:Profile">
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) Microsoft Corporation.
|
// Copyright (c) Microsoft Corporation.
|
||||||
// Licensed under the MIT license.
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
|
@ -7,6 +7,7 @@
|
||||||
#include "EnumEntry.h"
|
#include "EnumEntry.h"
|
||||||
|
|
||||||
#include <LibraryResources.h>
|
#include <LibraryResources.h>
|
||||||
|
#include "..\WinRTUtils\inc\Utils.h"
|
||||||
|
|
||||||
using namespace winrt::Windows::UI::Text;
|
using namespace winrt::Windows::UI::Text;
|
||||||
using namespace winrt::Windows::UI::Xaml;
|
using namespace winrt::Windows::UI::Xaml;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/*++
|
/*++
|
||||||
Copyright (c) Microsoft Corporation
|
Copyright (c) Microsoft Corporation
|
||||||
Licensed under the MIT license.
|
Licensed under the MIT license.
|
||||||
|
|
||||||
|
@ -93,6 +93,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||||
OBSERVABLE_PROJECTED_SETTING(_appearance, BackgroundImageStretchMode);
|
OBSERVABLE_PROJECTED_SETTING(_appearance, BackgroundImageStretchMode);
|
||||||
OBSERVABLE_PROJECTED_SETTING(_appearance, BackgroundImageAlignment);
|
OBSERVABLE_PROJECTED_SETTING(_appearance, BackgroundImageAlignment);
|
||||||
OBSERVABLE_PROJECTED_SETTING(_appearance, IntenseTextStyle);
|
OBSERVABLE_PROJECTED_SETTING(_appearance, IntenseTextStyle);
|
||||||
|
OBSERVABLE_PROJECTED_SETTING(_appearance, AdjustIndistinguishableColors);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Model::AppearanceConfig _appearance;
|
Model::AppearanceConfig _appearance;
|
||||||
|
|
|
@ -46,6 +46,7 @@ namespace Microsoft.Terminal.Settings.Editor
|
||||||
OBSERVABLE_PROJECTED_APPEARANCE_SETTING(Windows.UI.Xaml.Media.Stretch, BackgroundImageStretchMode);
|
OBSERVABLE_PROJECTED_APPEARANCE_SETTING(Windows.UI.Xaml.Media.Stretch, BackgroundImageStretchMode);
|
||||||
OBSERVABLE_PROJECTED_APPEARANCE_SETTING(Microsoft.Terminal.Settings.Model.ConvergedAlignment, BackgroundImageAlignment);
|
OBSERVABLE_PROJECTED_APPEARANCE_SETTING(Microsoft.Terminal.Settings.Model.ConvergedAlignment, BackgroundImageAlignment);
|
||||||
OBSERVABLE_PROJECTED_APPEARANCE_SETTING(Microsoft.Terminal.Settings.Model.IntenseStyle, IntenseTextStyle);
|
OBSERVABLE_PROJECTED_APPEARANCE_SETTING(Microsoft.Terminal.Settings.Model.IntenseStyle, IntenseTextStyle);
|
||||||
|
OBSERVABLE_PROJECTED_APPEARANCE_SETTING(Boolean, AdjustIndistinguishableColors);
|
||||||
}
|
}
|
||||||
|
|
||||||
[default_interface] runtimeclass Appearances : Windows.UI.Xaml.Controls.UserControl, Windows.UI.Xaml.Data.INotifyPropertyChanged
|
[default_interface] runtimeclass Appearances : Windows.UI.Xaml.Controls.UserControl, Windows.UI.Xaml.Data.INotifyPropertyChanged
|
||||||
|
|
|
@ -72,13 +72,15 @@
|
||||||
two font lists causes a crash within the ComboBox code.
|
two font lists causes a crash within the ComboBox code.
|
||||||
As a workaround, introduce two ComboBox controls and only display one at a time.
|
As a workaround, introduce two ComboBox controls and only display one at a time.
|
||||||
-->
|
-->
|
||||||
<ComboBox ItemTemplate="{StaticResource FontFaceComboBoxItemTemplate}"
|
<ComboBox x:Uid="Profile_FontFaceBox"
|
||||||
|
ItemTemplate="{StaticResource FontFaceComboBoxItemTemplate}"
|
||||||
ItemsSource="{x:Bind SourceProfile.MonospaceFontList, Mode=OneWay}"
|
ItemsSource="{x:Bind SourceProfile.MonospaceFontList, Mode=OneWay}"
|
||||||
SelectedItem="{x:Bind CurrentFontFace, Mode=OneWay}"
|
SelectedItem="{x:Bind CurrentFontFace, Mode=OneWay}"
|
||||||
SelectionChanged="FontFace_SelectionChanged"
|
SelectionChanged="FontFace_SelectionChanged"
|
||||||
Style="{StaticResource ComboBoxSettingStyle}"
|
Style="{StaticResource ComboBoxSettingStyle}"
|
||||||
Visibility="{x:Bind local:Converters.InvertedBooleanToVisibility(ShowAllFonts), Mode=OneWay}" />
|
Visibility="{x:Bind local:Converters.InvertedBooleanToVisibility(ShowAllFonts), Mode=OneWay}" />
|
||||||
<ComboBox ItemTemplate="{StaticResource FontFaceComboBoxItemTemplate}"
|
<ComboBox x:Uid="Profile_FontFaceBox"
|
||||||
|
ItemTemplate="{StaticResource FontFaceComboBoxItemTemplate}"
|
||||||
ItemsSource="{x:Bind SourceProfile.CompleteFontList, Mode=OneWay}"
|
ItemsSource="{x:Bind SourceProfile.CompleteFontList, Mode=OneWay}"
|
||||||
SelectedItem="{x:Bind CurrentFontFace, Mode=OneWay}"
|
SelectedItem="{x:Bind CurrentFontFace, Mode=OneWay}"
|
||||||
SelectionChanged="FontFace_SelectionChanged"
|
SelectionChanged="FontFace_SelectionChanged"
|
||||||
|
@ -97,7 +99,8 @@
|
||||||
HasSettingValue="{x:Bind Appearance.HasFontSize, Mode=OneWay}"
|
HasSettingValue="{x:Bind Appearance.HasFontSize, Mode=OneWay}"
|
||||||
SettingOverrideSource="{x:Bind Appearance.FontSizeOverrideSource, Mode=OneWay}"
|
SettingOverrideSource="{x:Bind Appearance.FontSizeOverrideSource, Mode=OneWay}"
|
||||||
Visibility="{x:Bind Appearance.IsDefault, Mode=OneWay}">
|
Visibility="{x:Bind Appearance.IsDefault, Mode=OneWay}">
|
||||||
<muxc:NumberBox AcceptsExpression="False"
|
<muxc:NumberBox x:Uid="Profile_FontSizeBox"
|
||||||
|
AcceptsExpression="False"
|
||||||
LargeChange="10"
|
LargeChange="10"
|
||||||
Maximum="128"
|
Maximum="128"
|
||||||
Minimum="1"
|
Minimum="1"
|
||||||
|
@ -150,6 +153,14 @@
|
||||||
SettingOverrideSource="{x:Bind Appearance.RetroTerminalEffectOverrideSource, Mode=OneWay}">
|
SettingOverrideSource="{x:Bind Appearance.RetroTerminalEffectOverrideSource, Mode=OneWay}">
|
||||||
<ToggleSwitch IsOn="{x:Bind Appearance.RetroTerminalEffect, Mode=TwoWay}" />
|
<ToggleSwitch IsOn="{x:Bind Appearance.RetroTerminalEffect, Mode=TwoWay}" />
|
||||||
</local:SettingContainer>
|
</local:SettingContainer>
|
||||||
|
|
||||||
|
<!-- Adjust Indistinguishable Colors -->
|
||||||
|
<local:SettingContainer x:Uid="Profile_AdjustIndistinguishableColors"
|
||||||
|
ClearSettingValue="{x:Bind Appearance.ClearAdjustIndistinguishableColors}"
|
||||||
|
HasSettingValue="{x:Bind Appearance.HasAdjustIndistinguishableColors, Mode=OneWay}"
|
||||||
|
SettingOverrideSource="{x:Bind Appearance.AdjustIndistinguishableColorsOverrideSource, Mode=OneWay}">
|
||||||
|
<ToggleSwitch IsOn="{x:Bind Appearance.AdjustIndistinguishableColors, Mode=TwoWay}" />
|
||||||
|
</local:SettingContainer>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
<!-- Grouping: Cursor -->
|
<!-- Grouping: Cursor -->
|
||||||
|
@ -163,7 +174,8 @@
|
||||||
ClearSettingValue="{x:Bind Appearance.ClearCursorShape}"
|
ClearSettingValue="{x:Bind Appearance.ClearCursorShape}"
|
||||||
HasSettingValue="{x:Bind Appearance.HasCursorShape, Mode=OneWay}"
|
HasSettingValue="{x:Bind Appearance.HasCursorShape, Mode=OneWay}"
|
||||||
SettingOverrideSource="{x:Bind Appearance.CursorShapeOverrideSource, Mode=OneWay}">
|
SettingOverrideSource="{x:Bind Appearance.CursorShapeOverrideSource, Mode=OneWay}">
|
||||||
<muxc:RadioButtons ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
<muxc:RadioButtons AutomationProperties.AccessibilityView="Content"
|
||||||
|
ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
||||||
ItemsSource="{x:Bind CursorShapeList, Mode=OneWay}"
|
ItemsSource="{x:Bind CursorShapeList, Mode=OneWay}"
|
||||||
SelectedItem="{x:Bind CurrentCursorShape, Mode=TwoWay}" />
|
SelectedItem="{x:Bind CurrentCursorShape, Mode=TwoWay}" />
|
||||||
</local:SettingContainer>
|
</local:SettingContainer>
|
||||||
|
@ -226,7 +238,8 @@
|
||||||
HasSettingValue="{x:Bind Appearance.HasBackgroundImageStretchMode, Mode=OneWay}"
|
HasSettingValue="{x:Bind Appearance.HasBackgroundImageStretchMode, Mode=OneWay}"
|
||||||
SettingOverrideSource="{x:Bind Appearance.BackgroundImageStretchModeOverrideSource, Mode=OneWay}"
|
SettingOverrideSource="{x:Bind Appearance.BackgroundImageStretchModeOverrideSource, Mode=OneWay}"
|
||||||
Visibility="{x:Bind Appearance.BackgroundImageSettingsVisible, Mode=OneWay}">
|
Visibility="{x:Bind Appearance.BackgroundImageSettingsVisible, Mode=OneWay}">
|
||||||
<muxc:RadioButtons ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
<muxc:RadioButtons AutomationProperties.AccessibilityView="Content"
|
||||||
|
ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
||||||
ItemsSource="{x:Bind BackgroundImageStretchModeList, Mode=OneWay}"
|
ItemsSource="{x:Bind BackgroundImageStretchModeList, Mode=OneWay}"
|
||||||
SelectedItem="{x:Bind CurrentBackgroundImageStretchMode, Mode=TwoWay}" />
|
SelectedItem="{x:Bind CurrentBackgroundImageStretchMode, Mode=TwoWay}" />
|
||||||
</local:SettingContainer>
|
</local:SettingContainer>
|
||||||
|
@ -441,7 +454,8 @@
|
||||||
ClearSettingValue="{x:Bind Appearance.ClearIntenseTextStyle}"
|
ClearSettingValue="{x:Bind Appearance.ClearIntenseTextStyle}"
|
||||||
HasSettingValue="{x:Bind Appearance.HasIntenseTextStyle, Mode=OneWay}"
|
HasSettingValue="{x:Bind Appearance.HasIntenseTextStyle, Mode=OneWay}"
|
||||||
SettingOverrideSource="{x:Bind Appearance.IntenseTextStyleOverrideSource, Mode=OneWay}">
|
SettingOverrideSource="{x:Bind Appearance.IntenseTextStyleOverrideSource, Mode=OneWay}">
|
||||||
<muxc:RadioButtons ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
<muxc:RadioButtons AutomationProperties.AccessibilityView="Content"
|
||||||
|
ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
||||||
ItemsSource="{x:Bind IntenseTextStyleList, Mode=OneWay}"
|
ItemsSource="{x:Bind IntenseTextStyleList, Mode=OneWay}"
|
||||||
SelectedItem="{x:Bind CurrentIntenseTextStyle, Mode=TwoWay}" />
|
SelectedItem="{x:Bind CurrentIntenseTextStyle, Mode=TwoWay}" />
|
||||||
</local:SettingContainer>
|
</local:SettingContainer>
|
||||||
|
|
|
@ -42,7 +42,8 @@
|
||||||
|
|
||||||
<!-- Theme -->
|
<!-- Theme -->
|
||||||
<local:SettingContainer x:Uid="Globals_Theme">
|
<local:SettingContainer x:Uid="Globals_Theme">
|
||||||
<muxc:RadioButtons ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
<muxc:RadioButtons AutomationProperties.AccessibilityView="Content"
|
||||||
|
ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
||||||
ItemsSource="{x:Bind ThemeList, Mode=OneWay}"
|
ItemsSource="{x:Bind ThemeList, Mode=OneWay}"
|
||||||
SelectedItem="{x:Bind CurrentTheme, Mode=TwoWay}" />
|
SelectedItem="{x:Bind CurrentTheme, Mode=TwoWay}" />
|
||||||
</local:SettingContainer>
|
</local:SettingContainer>
|
||||||
|
@ -74,7 +75,8 @@
|
||||||
|
|
||||||
<!-- Tab Width Mode -->
|
<!-- Tab Width Mode -->
|
||||||
<local:SettingContainer x:Uid="Globals_TabWidthMode">
|
<local:SettingContainer x:Uid="Globals_TabWidthMode">
|
||||||
<muxc:RadioButtons ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
<muxc:RadioButtons AutomationProperties.AccessibilityView="Content"
|
||||||
|
ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
||||||
ItemsSource="{x:Bind TabWidthModeList, Mode=OneWay}"
|
ItemsSource="{x:Bind TabWidthModeList, Mode=OneWay}"
|
||||||
SelectedItem="{x:Bind CurrentTabWidthMode, Mode=TwoWay}" />
|
SelectedItem="{x:Bind CurrentTabWidthMode, Mode=TwoWay}" />
|
||||||
</local:SettingContainer>
|
</local:SettingContainer>
|
||||||
|
|
|
@ -34,7 +34,8 @@
|
||||||
|
|
||||||
<!-- Copy Format -->
|
<!-- Copy Format -->
|
||||||
<local:SettingContainer x:Uid="Globals_CopyFormat">
|
<local:SettingContainer x:Uid="Globals_CopyFormat">
|
||||||
<muxc:RadioButtons ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
<muxc:RadioButtons AutomationProperties.AccessibilityView="Content"
|
||||||
|
ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
||||||
ItemsSource="{x:Bind CopyFormatList, Mode=OneWay}"
|
ItemsSource="{x:Bind CopyFormatList, Mode=OneWay}"
|
||||||
SelectedItem="{x:Bind CurrentCopyFormat, Mode=TwoWay}" />
|
SelectedItem="{x:Bind CurrentCopyFormat, Mode=TwoWay}" />
|
||||||
</local:SettingContainer>
|
</local:SettingContainer>
|
||||||
|
@ -58,7 +59,8 @@
|
||||||
|
|
||||||
<!-- Tab Switcher Mode -->
|
<!-- Tab Switcher Mode -->
|
||||||
<local:SettingContainer x:Uid="Globals_TabSwitcherMode">
|
<local:SettingContainer x:Uid="Globals_TabSwitcherMode">
|
||||||
<muxc:RadioButtons ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
<muxc:RadioButtons AutomationProperties.AccessibilityView="Content"
|
||||||
|
ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
||||||
ItemsSource="{x:Bind TabSwitcherModeList}"
|
ItemsSource="{x:Bind TabSwitcherModeList}"
|
||||||
SelectedItem="{x:Bind CurrentTabSwitcherMode, Mode=TwoWay}" />
|
SelectedItem="{x:Bind CurrentTabSwitcherMode, Mode=TwoWay}" />
|
||||||
</local:SettingContainer>
|
</local:SettingContainer>
|
||||||
|
|
|
@ -136,22 +136,26 @@
|
||||||
<!-- First Window Behavior -->
|
<!-- First Window Behavior -->
|
||||||
<local:SettingContainer x:Uid="Globals_FirstWindowPreference"
|
<local:SettingContainer x:Uid="Globals_FirstWindowPreference"
|
||||||
Visibility="{x:Bind ShowFirstWindowPreference}">
|
Visibility="{x:Bind ShowFirstWindowPreference}">
|
||||||
<muxc:RadioButtons ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
<muxc:RadioButtons AutomationProperties.AccessibilityView="Content"
|
||||||
|
ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
||||||
ItemsSource="{x:Bind FirstWindowPreferenceList}"
|
ItemsSource="{x:Bind FirstWindowPreferenceList}"
|
||||||
SelectedItem="{x:Bind CurrentFirstWindowPreference, Mode=TwoWay}" />
|
SelectedItem="{x:Bind CurrentFirstWindowPreference, Mode=TwoWay}" />
|
||||||
</local:SettingContainer>
|
</local:SettingContainer>
|
||||||
|
|
||||||
|
|
||||||
<!-- Launch Mode -->
|
<!-- Launch Mode -->
|
||||||
<local:SettingContainer x:Uid="Globals_LaunchMode">
|
<local:SettingContainer x:Name="Globals_LaunchMode"
|
||||||
<muxc:RadioButtons ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
x:Uid="Globals_LaunchMode">
|
||||||
|
<muxc:RadioButtons AutomationProperties.AccessibilityView="Content"
|
||||||
|
ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
||||||
ItemsSource="{x:Bind LaunchModeList}"
|
ItemsSource="{x:Bind LaunchModeList}"
|
||||||
SelectedItem="{x:Bind CurrentLaunchMode, Mode=TwoWay}" />
|
SelectedItem="{x:Bind CurrentLaunchMode, Mode=TwoWay}" />
|
||||||
</local:SettingContainer>
|
</local:SettingContainer>
|
||||||
|
|
||||||
<!-- Launch Mode -->
|
<!-- Launch Mode -->
|
||||||
<local:SettingContainer x:Uid="Globals_WindowingBehavior">
|
<local:SettingContainer x:Uid="Globals_WindowingBehavior">
|
||||||
<muxc:RadioButtons ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
<muxc:RadioButtons AutomationProperties.AccessibilityView="Content"
|
||||||
|
ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
||||||
ItemsSource="{x:Bind WindowingBehaviorList}"
|
ItemsSource="{x:Bind WindowingBehaviorList}"
|
||||||
SelectedItem="{x:Bind CurrentWindowingBehavior, Mode=TwoWay}" />
|
SelectedItem="{x:Bind CurrentWindowingBehavior, Mode=TwoWay}" />
|
||||||
</local:SettingContainer>
|
</local:SettingContainer>
|
||||||
|
@ -166,12 +170,14 @@
|
||||||
<!-- Columns -->
|
<!-- Columns -->
|
||||||
<local:SettingContainer x:Uid="Globals_InitialCols"
|
<local:SettingContainer x:Uid="Globals_InitialCols"
|
||||||
Margin="0">
|
Margin="0">
|
||||||
<muxc:NumberBox Style="{StaticResource LaunchSizeNumberBoxStyle}"
|
<muxc:NumberBox x:Uid="Globals_InitialColsBox"
|
||||||
|
Style="{StaticResource LaunchSizeNumberBoxStyle}"
|
||||||
Value="{x:Bind State.Settings.GlobalSettings.InitialCols, Mode=TwoWay}" />
|
Value="{x:Bind State.Settings.GlobalSettings.InitialCols, Mode=TwoWay}" />
|
||||||
</local:SettingContainer>
|
</local:SettingContainer>
|
||||||
<!-- Rows -->
|
<!-- Rows -->
|
||||||
<local:SettingContainer x:Uid="Globals_InitialRows">
|
<local:SettingContainer x:Uid="Globals_InitialRows">
|
||||||
<muxc:NumberBox Style="{StaticResource LaunchSizeNumberBoxStyle}"
|
<muxc:NumberBox x:Uid="Globals_InitialRowsBox"
|
||||||
|
Style="{StaticResource LaunchSizeNumberBoxStyle}"
|
||||||
Value="{x:Bind State.Settings.GlobalSettings.InitialRows, Mode=TwoWay}" />
|
Value="{x:Bind State.Settings.GlobalSettings.InitialRows, Mode=TwoWay}" />
|
||||||
</local:SettingContainer>
|
</local:SettingContainer>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) Microsoft Corporation.
|
// Copyright (c) Microsoft Corporation.
|
||||||
// Licensed under the MIT license.
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
|
@ -8,6 +8,7 @@
|
||||||
#include "EnumEntry.h"
|
#include "EnumEntry.h"
|
||||||
|
|
||||||
#include <LibraryResources.h>
|
#include <LibraryResources.h>
|
||||||
|
#include "..\WinRTUtils\inc\Utils.h"
|
||||||
|
|
||||||
using namespace winrt::Windows::UI::Text;
|
using namespace winrt::Windows::UI::Text;
|
||||||
using namespace winrt::Windows::UI::Xaml;
|
using namespace winrt::Windows::UI::Xaml;
|
||||||
|
@ -46,6 +47,22 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||||
// NOTE: this is similar to what is done with BackgroundImagePath above
|
// NOTE: this is similar to what is done with BackgroundImagePath above
|
||||||
_NotifyChanges(L"UseParentProcessDirectory", L"UseCustomStartingDirectory");
|
_NotifyChanges(L"UseParentProcessDirectory", L"UseCustomStartingDirectory");
|
||||||
}
|
}
|
||||||
|
else if (viewModelProperty == L"UseAcrylic")
|
||||||
|
{
|
||||||
|
// GH#11372: If we're on Windows 10, and someone turns off
|
||||||
|
// acrylic, we're going to disable opacity for them. Opacity
|
||||||
|
// doesn't work without acrylic on Windows 10.
|
||||||
|
//
|
||||||
|
// BODGY: CascadiaSettings's function IsDefaultTerminalAvailable
|
||||||
|
// is basically a "are we on Windows 11" check, because defterm
|
||||||
|
// only works on Win11. So we'll use that.
|
||||||
|
//
|
||||||
|
// Remove when we can remove the rest of GH#11285
|
||||||
|
if (!UseAcrylic() && !CascadiaSettings::IsDefaultTerminalAvailable())
|
||||||
|
{
|
||||||
|
Opacity(1.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Do the same for the starting directory
|
// Do the same for the starting directory
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) Microsoft Corporation.
|
// Copyright (c) Microsoft Corporation.
|
||||||
// Licensed under the MIT license.
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
@ -22,7 +22,21 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||||
|
|
||||||
void SetAcrylicOpacityPercentageValue(double value)
|
void SetAcrylicOpacityPercentageValue(double value)
|
||||||
{
|
{
|
||||||
_profile.DefaultAppearance().Opacity(winrt::Microsoft::Terminal::Settings::Editor::Converters::PercentageValueToPercentage(value));
|
Opacity(winrt::Microsoft::Terminal::Settings::Editor::Converters::PercentageValueToPercentage(value));
|
||||||
|
|
||||||
|
// GH#11372: If we're on Windows 10, and someone wants opacity, then
|
||||||
|
// we'll turn acrylic on for them. Opacity doesn't work without
|
||||||
|
// acrylic on Windows 10.
|
||||||
|
//
|
||||||
|
// BODGY: CascadiaSettings's function IsDefaultTerminalAvailable
|
||||||
|
// is basically a "are we on Windows 11" check, because defterm
|
||||||
|
// only works on Win11. So we'll use that.
|
||||||
|
//
|
||||||
|
// Remove when we can remove the rest of GH#11285
|
||||||
|
if (value < 100.0 && winrt::Microsoft::Terminal::Settings::Model::CascadiaSettings::IsDefaultTerminalAvailable())
|
||||||
|
{
|
||||||
|
UseAcrylic(true);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void SetPadding(double value)
|
void SetPadding(double value)
|
||||||
|
|
|
@ -81,7 +81,8 @@
|
||||||
SettingOverrideSource="{x:Bind State.Profile.CommandlineOverrideSource, Mode=OneWay}"
|
SettingOverrideSource="{x:Bind State.Profile.CommandlineOverrideSource, Mode=OneWay}"
|
||||||
Visibility="{x:Bind local:Converters.InvertedBooleanToVisibility(State.Profile.IsBaseLayer), Mode=OneWay}">
|
Visibility="{x:Bind local:Converters.InvertedBooleanToVisibility(State.Profile.IsBaseLayer), Mode=OneWay}">
|
||||||
<StackPanel Orientation="Horizontal">
|
<StackPanel Orientation="Horizontal">
|
||||||
<TextBox IsSpellCheckEnabled="False"
|
<TextBox x:Uid="Profile_CommandlineBox"
|
||||||
|
IsSpellCheckEnabled="False"
|
||||||
Style="{StaticResource TextBoxSettingStyle}"
|
Style="{StaticResource TextBoxSettingStyle}"
|
||||||
Text="{x:Bind State.Profile.Commandline, Mode=TwoWay}" />
|
Text="{x:Bind State.Profile.Commandline, Mode=TwoWay}" />
|
||||||
<Button x:Uid="Profile_CommandlineBrowse"
|
<Button x:Uid="Profile_CommandlineBrowse"
|
||||||
|
@ -99,7 +100,8 @@
|
||||||
SettingOverrideSource="{x:Bind State.Profile.StartingDirectoryOverrideSource, Mode=OneWay}">
|
SettingOverrideSource="{x:Bind State.Profile.StartingDirectoryOverrideSource, Mode=OneWay}">
|
||||||
<StackPanel Orientation="Vertical">
|
<StackPanel Orientation="Vertical">
|
||||||
<StackPanel Orientation="Horizontal">
|
<StackPanel Orientation="Horizontal">
|
||||||
<TextBox IsEnabled="{x:Bind State.Profile.UseCustomStartingDirectory, Mode=OneWay}"
|
<TextBox x:Uid="Profile_StartingDirectoryBox"
|
||||||
|
IsEnabled="{x:Bind State.Profile.UseCustomStartingDirectory, Mode=OneWay}"
|
||||||
IsSpellCheckEnabled="False"
|
IsSpellCheckEnabled="False"
|
||||||
Style="{StaticResource TextBoxSettingStyle}"
|
Style="{StaticResource TextBoxSettingStyle}"
|
||||||
Text="{x:Bind State.Profile.StartingDirectory, Mode=TwoWay}" />
|
Text="{x:Bind State.Profile.StartingDirectory, Mode=TwoWay}" />
|
||||||
|
@ -121,7 +123,8 @@
|
||||||
HasSettingValue="{x:Bind State.Profile.HasIcon, Mode=OneWay}"
|
HasSettingValue="{x:Bind State.Profile.HasIcon, Mode=OneWay}"
|
||||||
SettingOverrideSource="{x:Bind State.Profile.IconOverrideSource, Mode=OneWay}">
|
SettingOverrideSource="{x:Bind State.Profile.IconOverrideSource, Mode=OneWay}">
|
||||||
<StackPanel Orientation="Horizontal">
|
<StackPanel Orientation="Horizontal">
|
||||||
<TextBox FontFamily="Segoe UI, Segoe MDL2 Assets"
|
<TextBox x:Uid="Profile_IconBox"
|
||||||
|
FontFamily="Segoe UI, Segoe MDL2 Assets"
|
||||||
IsSpellCheckEnabled="False"
|
IsSpellCheckEnabled="False"
|
||||||
Style="{StaticResource TextBoxSettingStyle}"
|
Style="{StaticResource TextBoxSettingStyle}"
|
||||||
Text="{x:Bind State.Profile.Icon, Mode=TwoWay}" />
|
Text="{x:Bind State.Profile.Icon, Mode=TwoWay}" />
|
||||||
|
@ -246,6 +249,7 @@
|
||||||
<!-- Opacity -->
|
<!-- Opacity -->
|
||||||
<local:SettingContainer x:Name="OpacityContainer"
|
<local:SettingContainer x:Name="OpacityContainer"
|
||||||
x:Uid="Profile_Opacity"
|
x:Uid="Profile_Opacity"
|
||||||
|
Margin="0"
|
||||||
ClearSettingValue="{x:Bind State.Profile.ClearOpacity}"
|
ClearSettingValue="{x:Bind State.Profile.ClearOpacity}"
|
||||||
HasSettingValue="{x:Bind State.Profile.HasOpacity, Mode=OneWay}"
|
HasSettingValue="{x:Bind State.Profile.HasOpacity, Mode=OneWay}"
|
||||||
SettingOverrideSource="{x:Bind State.Profile.OpacityOverrideSource, Mode=OneWay}">
|
SettingOverrideSource="{x:Bind State.Profile.OpacityOverrideSource, Mode=OneWay}">
|
||||||
|
@ -307,7 +311,8 @@
|
||||||
ClearSettingValue="{x:Bind State.Profile.ClearScrollState}"
|
ClearSettingValue="{x:Bind State.Profile.ClearScrollState}"
|
||||||
HasSettingValue="{x:Bind State.Profile.HasScrollState, Mode=OneWay}"
|
HasSettingValue="{x:Bind State.Profile.HasScrollState, Mode=OneWay}"
|
||||||
SettingOverrideSource="{x:Bind State.Profile.ScrollStateOverrideSource, Mode=OneWay}">
|
SettingOverrideSource="{x:Bind State.Profile.ScrollStateOverrideSource, Mode=OneWay}">
|
||||||
<muxc:RadioButtons ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
<muxc:RadioButtons AutomationProperties.AccessibilityView="Content"
|
||||||
|
ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
||||||
ItemsSource="{x:Bind ScrollStateList, Mode=OneWay}"
|
ItemsSource="{x:Bind ScrollStateList, Mode=OneWay}"
|
||||||
SelectedItem="{x:Bind CurrentScrollState, Mode=TwoWay}" />
|
SelectedItem="{x:Bind CurrentScrollState, Mode=TwoWay}" />
|
||||||
</local:SettingContainer>
|
</local:SettingContainer>
|
||||||
|
@ -412,7 +417,8 @@
|
||||||
ClearSettingValue="{x:Bind State.Profile.ClearAntialiasingMode}"
|
ClearSettingValue="{x:Bind State.Profile.ClearAntialiasingMode}"
|
||||||
HasSettingValue="{x:Bind State.Profile.HasAntialiasingMode, Mode=OneWay}"
|
HasSettingValue="{x:Bind State.Profile.HasAntialiasingMode, Mode=OneWay}"
|
||||||
SettingOverrideSource="{x:Bind State.Profile.AntialiasingModeOverrideSource, Mode=OneWay}">
|
SettingOverrideSource="{x:Bind State.Profile.AntialiasingModeOverrideSource, Mode=OneWay}">
|
||||||
<muxc:RadioButtons ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
<muxc:RadioButtons AutomationProperties.AccessibilityView="Content"
|
||||||
|
ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
||||||
ItemsSource="{x:Bind AntiAliasingModeList, Mode=OneWay}"
|
ItemsSource="{x:Bind AntiAliasingModeList, Mode=OneWay}"
|
||||||
SelectedItem="{x:Bind CurrentAntiAliasingMode, Mode=TwoWay}" />
|
SelectedItem="{x:Bind CurrentAntiAliasingMode, Mode=TwoWay}" />
|
||||||
</local:SettingContainer>
|
</local:SettingContainer>
|
||||||
|
@ -438,7 +444,8 @@
|
||||||
ClearSettingValue="{x:Bind State.Profile.ClearHistorySize}"
|
ClearSettingValue="{x:Bind State.Profile.ClearHistorySize}"
|
||||||
HasSettingValue="{x:Bind State.Profile.HasHistorySize, Mode=OneWay}"
|
HasSettingValue="{x:Bind State.Profile.HasHistorySize, Mode=OneWay}"
|
||||||
SettingOverrideSource="{x:Bind State.Profile.HistorySizeOverrideSource, Mode=OneWay}">
|
SettingOverrideSource="{x:Bind State.Profile.HistorySizeOverrideSource, Mode=OneWay}">
|
||||||
<muxc:NumberBox LargeChange="100"
|
<muxc:NumberBox x:Uid="Profile_HistorySizeBox"
|
||||||
|
LargeChange="100"
|
||||||
Minimum="0"
|
Minimum="0"
|
||||||
SmallChange="10"
|
SmallChange="10"
|
||||||
Style="{StaticResource NumberBoxSettingStyle}"
|
Style="{StaticResource NumberBoxSettingStyle}"
|
||||||
|
@ -450,7 +457,8 @@
|
||||||
ClearSettingValue="{x:Bind State.Profile.ClearCloseOnExit}"
|
ClearSettingValue="{x:Bind State.Profile.ClearCloseOnExit}"
|
||||||
HasSettingValue="{x:Bind State.Profile.HasCloseOnExit, Mode=OneWay}"
|
HasSettingValue="{x:Bind State.Profile.HasCloseOnExit, Mode=OneWay}"
|
||||||
SettingOverrideSource="{x:Bind State.Profile.CloseOnExitOverrideSource, Mode=OneWay}">
|
SettingOverrideSource="{x:Bind State.Profile.CloseOnExitOverrideSource, Mode=OneWay}">
|
||||||
<muxc:RadioButtons ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
<muxc:RadioButtons AutomationProperties.AccessibilityView="Content"
|
||||||
|
ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
||||||
ItemsSource="{x:Bind CloseOnExitModeList, Mode=OneWay}"
|
ItemsSource="{x:Bind CloseOnExitModeList, Mode=OneWay}"
|
||||||
SelectedItem="{x:Bind CurrentCloseOnExitMode, Mode=TwoWay}" />
|
SelectedItem="{x:Bind CurrentCloseOnExitMode, Mode=TwoWay}" />
|
||||||
</local:SettingContainer>
|
</local:SettingContainer>
|
||||||
|
|
|
@ -291,6 +291,14 @@
|
||||||
<value>The number of rows displayed in the window upon first load. Measured in characters.</value>
|
<value>The number of rows displayed in the window upon first load. Measured in characters.</value>
|
||||||
<comment>A description for what the "rows" setting does. Presented near "Globals_InitialRows.Header".</comment>
|
<comment>A description for what the "rows" setting does. Presented near "Globals_InitialRows.Header".</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Globals_InitialColsBox.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||||
|
<value>Initial Columns</value>
|
||||||
|
<comment>Name for a control to choose the number of columns in the terminal's text grid.</comment>
|
||||||
|
</data>
|
||||||
|
<data name="Globals_InitialRowsBox.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||||
|
<value>Initial Rows</value>
|
||||||
|
<comment>Name for a control to choose the number of rows in the terminal's text grid.</comment>
|
||||||
|
</data>
|
||||||
<data name="Globals_FirstWindowPreference.Header" xml:space="preserve">
|
<data name="Globals_FirstWindowPreference.Header" xml:space="preserve">
|
||||||
<value>When Terminal starts</value>
|
<value>When Terminal starts</value>
|
||||||
<comment>Header for a control to select how the terminal should load its first window.</comment>
|
<comment>Header for a control to select how the terminal should load its first window.</comment>
|
||||||
|
@ -304,8 +312,8 @@
|
||||||
<comment>An option to choose from for the "First window preference" setting. Open the default profile.</comment>
|
<comment>An option to choose from for the "First window preference" setting. Open the default profile.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="Globals_FirstWindowPreferencePersistedWindowLayout.Content" xml:space="preserve">
|
<data name="Globals_FirstWindowPreferencePersistedWindowLayout.Content" xml:space="preserve">
|
||||||
<value>Open tabs from a previous session</value>
|
<value>Open windows from a previous session</value>
|
||||||
<comment>An option to choose from for the "First window preference" setting. Reopen the layout from the last session.</comment>
|
<comment>An option to choose from for the "First window preference" setting. Reopen the layouts from the last session.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="Globals_LaunchMode.Header" xml:space="preserve">
|
<data name="Globals_LaunchMode.Header" xml:space="preserve">
|
||||||
<value>Launch mode</value>
|
<value>Launch mode</value>
|
||||||
|
@ -496,7 +504,7 @@
|
||||||
<comment>A description for what the "acrylic opacity" setting does. Presented near "Profile_AcrylicOpacity.Header".</comment>
|
<comment>A description for what the "acrylic opacity" setting does. Presented near "Profile_AcrylicOpacity.Header".</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="Profile_Opacity.Header" xml:space="preserve">
|
<data name="Profile_Opacity.Header" xml:space="preserve">
|
||||||
<value>Background Opacity</value>
|
<value>Background opacity</value>
|
||||||
<comment>Header for a control to determine the level of opacity for the background of the control. The user can choose to make the background of the app more or less opaque.</comment>
|
<comment>Header for a control to determine the level of opacity for the background of the control. The user can choose to make the background of the app more or less opaque.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="Profile_Opacity.HelpText" xml:space="preserve">
|
<data name="Profile_Opacity.HelpText" xml:space="preserve">
|
||||||
|
@ -655,6 +663,10 @@
|
||||||
<value>Command line</value>
|
<value>Command line</value>
|
||||||
<comment>Header for a control to determine commandline executable (i.e. a .exe file) to run when a terminal session of this profile is launched.</comment>
|
<comment>Header for a control to determine commandline executable (i.e. a .exe file) to run when a terminal session of this profile is launched.</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Profile_CommandlineBox.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||||
|
<value>Command line</value>
|
||||||
|
<comment>Name for a control to determine commandline executable (i.e. a .exe file) to run when a terminal session of this profile is launched.</comment>
|
||||||
|
</data>
|
||||||
<data name="Profile_Commandline.HelpText" xml:space="preserve">
|
<data name="Profile_Commandline.HelpText" xml:space="preserve">
|
||||||
<value>Executable used in the profile.</value>
|
<value>Executable used in the profile.</value>
|
||||||
<comment>A description for what the "command line" setting does. Presented near "Profile_Commandline".</comment>
|
<comment>A description for what the "command line" setting does. Presented near "Profile_Commandline".</comment>
|
||||||
|
@ -703,6 +715,10 @@
|
||||||
<value>Font face</value>
|
<value>Font face</value>
|
||||||
<comment>Header for a control to select the font for text in the app.</comment>
|
<comment>Header for a control to select the font for text in the app.</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Profile_FontFaceBox.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||||
|
<value>Font face</value>
|
||||||
|
<comment>Name for a control to select the font for text in the app.</comment>
|
||||||
|
</data>
|
||||||
<data name="Profile_FontFace.HelpText" xml:space="preserve">
|
<data name="Profile_FontFace.HelpText" xml:space="preserve">
|
||||||
<value>Name of the font face used in the profile.</value>
|
<value>Name of the font face used in the profile.</value>
|
||||||
<comment>A description for what the "font face" setting does. Presented near "Profile_FontFace".</comment>
|
<comment>A description for what the "font face" setting does. Presented near "Profile_FontFace".</comment>
|
||||||
|
@ -711,6 +727,10 @@
|
||||||
<value>Font size</value>
|
<value>Font size</value>
|
||||||
<comment>Header for a control to determine the size of the text in the app.</comment>
|
<comment>Header for a control to determine the size of the text in the app.</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Profile_FontSizeBox.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||||
|
<value>Font size</value>
|
||||||
|
<comment>Name for a control to determine the size of the text in the app.</comment>
|
||||||
|
</data>
|
||||||
<data name="Profile_FontSize.HelpText" xml:space="preserve">
|
<data name="Profile_FontSize.HelpText" xml:space="preserve">
|
||||||
<value>Size of the font in points.</value>
|
<value>Size of the font in points.</value>
|
||||||
<comment>A description for what the "font size" setting does. Presented near "Profile_FontSize".</comment>
|
<comment>A description for what the "font size" setting does. Presented near "Profile_FontSize".</comment>
|
||||||
|
@ -739,6 +759,10 @@
|
||||||
<value>History size</value>
|
<value>History size</value>
|
||||||
<comment>Header for a control to determine how many lines of text can be saved in a session. In terminals, the "history" is the output generated within your session.</comment>
|
<comment>Header for a control to determine how many lines of text can be saved in a session. In terminals, the "history" is the output generated within your session.</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Profile_HistorySizeBox.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||||
|
<value>History size</value>
|
||||||
|
<comment>Name for a control to determine how many lines of text can be saved in a session. In terminals, the "history" is the output generated within your session.</comment>
|
||||||
|
</data>
|
||||||
<data name="Profile_HistorySize.HelpText" xml:space="preserve">
|
<data name="Profile_HistorySize.HelpText" xml:space="preserve">
|
||||||
<value>The number of lines above the ones displayed in the window you can scroll back to.</value>
|
<value>The number of lines above the ones displayed in the window you can scroll back to.</value>
|
||||||
<comment>A description for what the "history size" setting does. Presented near "Profile_HistorySize".</comment>
|
<comment>A description for what the "history size" setting does. Presented near "Profile_HistorySize".</comment>
|
||||||
|
@ -747,6 +771,10 @@
|
||||||
<value>Icon</value>
|
<value>Icon</value>
|
||||||
<comment>Header for a control to determine what icon can be used to represent this profile. This is not necessarily a file path, but can be one.</comment>
|
<comment>Header for a control to determine what icon can be used to represent this profile. This is not necessarily a file path, but can be one.</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Profile_IconBox.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||||
|
<value>Icon</value>
|
||||||
|
<comment>Name for a control to determine what icon can be used to represent this profile. This is not necessarily a file path, but can be one.</comment>
|
||||||
|
</data>
|
||||||
<data name="Profile_Icon.HelpText" xml:space="preserve">
|
<data name="Profile_Icon.HelpText" xml:space="preserve">
|
||||||
<value>Emoji or image file location of the icon used in the profile.</value>
|
<value>Emoji or image file location of the icon used in the profile.</value>
|
||||||
<comment>A description for what the "icon" setting does. Presented near "Profile_Icon".</comment>
|
<comment>A description for what the "icon" setting does. Presented near "Profile_Icon".</comment>
|
||||||
|
@ -771,6 +799,14 @@
|
||||||
<value>When enabled, enables retro terminal effects such as glowing text and scan lines.</value>
|
<value>When enabled, enables retro terminal effects such as glowing text and scan lines.</value>
|
||||||
<comment>A description for what the "retro terminal effects" setting does. Presented near "Profile_RetroTerminalEffect".</comment>
|
<comment>A description for what the "retro terminal effects" setting does. Presented near "Profile_RetroTerminalEffect".</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Profile_AdjustIndistinguishableColors.Header" xml:space="preserve">
|
||||||
|
<value>Automatically adjust lightness of indistinguishable text</value>
|
||||||
|
<comment>Header for a control to toggle if we should adjust the foreground color's lightness to make it more visible when necessary, based on the background color.</comment>
|
||||||
|
</data>
|
||||||
|
<data name="Profile_AdjustIndistinguishableColors.HelpText" xml:space="preserve">
|
||||||
|
<value>When enabled, enables automatic adjustment of indistinguishable colors, which will, only when necessary, adjust the foreground color's lightness to make it more visible (based on the background color).</value>
|
||||||
|
<comment>A description for what the "adjust indistinguishable colors" setting does. Presented near "Profile_AdjustIndistinguishableColors".</comment>
|
||||||
|
</data>
|
||||||
<data name="Profile_ScrollbarVisibility.Header" xml:space="preserve">
|
<data name="Profile_ScrollbarVisibility.Header" xml:space="preserve">
|
||||||
<value>Scrollbar visibility</value>
|
<value>Scrollbar visibility</value>
|
||||||
<comment>Header for a control to select the visibility of the scrollbar in a session.</comment>
|
<comment>Header for a control to select the visibility of the scrollbar in a session.</comment>
|
||||||
|
@ -791,6 +827,10 @@
|
||||||
<value>Starting directory</value>
|
<value>Starting directory</value>
|
||||||
<comment>Header for a control to determine the directory the session opens it at launch. This is on a text box that accepts folder paths.</comment>
|
<comment>Header for a control to determine the directory the session opens it at launch. This is on a text box that accepts folder paths.</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Profile_StartingDirectoryBox.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||||
|
<value>Starting directory</value>
|
||||||
|
<comment>Name for a control to determine the directory the session opens it at launch. This is on a text box that accepts folder paths.</comment>
|
||||||
|
</data>
|
||||||
<data name="Profile_StartingDirectory.HelpText" xml:space="preserve">
|
<data name="Profile_StartingDirectory.HelpText" xml:space="preserve">
|
||||||
<value>The directory the profile starts in when it is loaded.</value>
|
<value>The directory the profile starts in when it is loaded.</value>
|
||||||
<comment>A description for what the "starting directory" setting does. Presented near "Profile_StartingDirectory".</comment>
|
<comment>A description for what the "starting directory" setting does. Presented near "Profile_StartingDirectory".</comment>
|
||||||
|
@ -1227,7 +1267,7 @@
|
||||||
<comment>Header for a control to how text is formatted</comment>
|
<comment>Header for a control to how text is formatted</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="Appearance_IntenseTextStyle.Header" xml:space="preserve">
|
<data name="Appearance_IntenseTextStyle.Header" xml:space="preserve">
|
||||||
<value>Intense Text Style</value>
|
<value>Intense text style</value>
|
||||||
<comment>Header for a control to select how "intense" text is formatted (bold, bright, both or none)</comment>
|
<comment>Header for a control to select how "intense" text is formatted (bold, bright, both or none)</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="Appearance_IntenseTextStyleNone.Content" xml:space="preserve">
|
<data name="Appearance_IntenseTextStyleNone.Content" xml:space="preserve">
|
||||||
|
|
|
@ -15,30 +15,6 @@ using namespace winrt::Windows::UI::Xaml;
|
||||||
|
|
||||||
UTILS_DEFINE_LIBRARY_RESOURCE_SCOPE(L"Microsoft.Terminal.Settings.Editor/Resources");
|
UTILS_DEFINE_LIBRARY_RESOURCE_SCOPE(L"Microsoft.Terminal.Settings.Editor/Resources");
|
||||||
|
|
||||||
// Function Description:
|
|
||||||
// - Helper that opens a file picker pre-seeded with image file types.
|
|
||||||
winrt::Windows::Foundation::IAsyncOperation<winrt::hstring> OpenImagePicker(HWND parentHwnd)
|
|
||||||
{
|
|
||||||
static constexpr COMDLG_FILTERSPEC supportedImageFileTypes[] = {
|
|
||||||
{ L"All Supported Bitmap Types (*.jpg, *.jpeg, *.png, *.bmp, *.gif, *.tiff, *.ico)", L"*.jpg;*.jpeg;*.png;*.bmp;*.gif;*.tiff;*.ico" },
|
|
||||||
{ L"All Files (*.*)", L"*.*" }
|
|
||||||
};
|
|
||||||
|
|
||||||
static constexpr winrt::guid clientGuidImagePicker{ 0x55675F54, 0x74A1, 0x4552, { 0xA3, 0x9D, 0x94, 0xAE, 0x85, 0xD8, 0xF2, 0x7A } };
|
|
||||||
return OpenFilePicker(parentHwnd, [](auto&& dialog) {
|
|
||||||
THROW_IF_FAILED(dialog->SetClientGuid(clientGuidImagePicker));
|
|
||||||
try
|
|
||||||
{
|
|
||||||
auto pictureFolderShellItem{ winrt::capture<IShellItem>(&SHGetKnownFolderItem, FOLDERID_PicturesLibrary, KF_FLAG_DEFAULT, nullptr) };
|
|
||||||
dialog->SetDefaultFolder(pictureFolderShellItem.get());
|
|
||||||
}
|
|
||||||
CATCH_LOG(); // non-fatal
|
|
||||||
THROW_IF_FAILED(dialog->SetFileTypes(ARRAYSIZE(supportedImageFileTypes), supportedImageFileTypes));
|
|
||||||
THROW_IF_FAILED(dialog->SetFileTypeIndex(1)); // the array is 1-indexed
|
|
||||||
THROW_IF_FAILED(dialog->SetDefaultExtension(L"jpg;jpeg;png;bmp;gif;tiff;ico"));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace winrt::Microsoft::Terminal::Settings
|
namespace winrt::Microsoft::Terminal::Settings
|
||||||
{
|
{
|
||||||
hstring GetSelectedItemTag(winrt::Windows::Foundation::IInspectable const& comboBoxAsInspectable)
|
hstring GetSelectedItemTag(winrt::Windows::Foundation::IInspectable const& comboBoxAsInspectable)
|
||||||
|
|
|
@ -97,42 +97,6 @@ public: \
|
||||||
private: \
|
private: \
|
||||||
static winrt::Windows::UI::Xaml::DependencyProperty _##name##Property;
|
static winrt::Windows::UI::Xaml::DependencyProperty _##name##Property;
|
||||||
|
|
||||||
// Function Description:
|
|
||||||
// - This function presents a File Open "common dialog" and returns its selected file asynchronously.
|
|
||||||
// Parameters:
|
|
||||||
// - customize: A lambda that receives an IFileDialog* to customize.
|
|
||||||
// Return value:
|
|
||||||
// (async) path to the selected item.
|
|
||||||
template<typename TLambda>
|
|
||||||
winrt::Windows::Foundation::IAsyncOperation<winrt::hstring> OpenFilePicker(HWND parentHwnd, TLambda&& customize)
|
|
||||||
{
|
|
||||||
auto fileDialog{ winrt::create_instance<IFileDialog>(CLSID_FileOpenDialog) };
|
|
||||||
DWORD flags{};
|
|
||||||
THROW_IF_FAILED(fileDialog->GetOptions(&flags));
|
|
||||||
THROW_IF_FAILED(fileDialog->SetOptions(flags | FOS_FORCEFILESYSTEM | FOS_NOCHANGEDIR | FOS_DONTADDTORECENT)); // filesystem objects only; no recent places
|
|
||||||
customize(fileDialog.get());
|
|
||||||
|
|
||||||
auto hr{ fileDialog->Show(parentHwnd) };
|
|
||||||
if (!SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
if (hr == HRESULT_FROM_WIN32(ERROR_CANCELLED))
|
|
||||||
{
|
|
||||||
co_return winrt::hstring{};
|
|
||||||
}
|
|
||||||
THROW_HR(hr);
|
|
||||||
}
|
|
||||||
|
|
||||||
winrt::com_ptr<IShellItem> result;
|
|
||||||
THROW_IF_FAILED(fileDialog->GetResult(result.put()));
|
|
||||||
|
|
||||||
wil::unique_cotaskmem_string filePath;
|
|
||||||
THROW_IF_FAILED(result->GetDisplayName(SIGDN_FILESYSPATH, &filePath));
|
|
||||||
|
|
||||||
co_return winrt::hstring{ filePath.get() };
|
|
||||||
}
|
|
||||||
|
|
||||||
winrt::Windows::Foundation::IAsyncOperation<winrt::hstring> OpenImagePicker(HWND parentHwnd);
|
|
||||||
|
|
||||||
namespace winrt::Microsoft::Terminal::Settings
|
namespace winrt::Microsoft::Terminal::Settings
|
||||||
{
|
{
|
||||||
winrt::hstring GetSelectedItemTag(winrt::Windows::Foundation::IInspectable const& comboBoxAsInspectable);
|
winrt::hstring GetSelectedItemTag(winrt::Windows::Foundation::IInspectable const& comboBoxAsInspectable);
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
#include "MultipleActionsArgs.g.cpp"
|
#include "MultipleActionsArgs.g.cpp"
|
||||||
|
|
||||||
#include <LibraryResources.h>
|
#include <LibraryResources.h>
|
||||||
|
#include <WtExeUtils.h>
|
||||||
|
|
||||||
using namespace winrt::Microsoft::Terminal::Control;
|
using namespace winrt::Microsoft::Terminal::Control;
|
||||||
|
|
||||||
|
@ -121,15 +122,12 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||||
|
|
||||||
if (!StartingDirectory().empty())
|
if (!StartingDirectory().empty())
|
||||||
{
|
{
|
||||||
// If the directory ends in a '\', we need to add another one on so that the enclosing quote added
|
ss << fmt::format(L"--startingDirectory {} ", QuoteAndEscapeCommandlineArg(StartingDirectory()));
|
||||||
// afterwards isn't escaped
|
|
||||||
const auto trailingBackslashEscape = StartingDirectory().back() == L'\\' ? L"\\" : L"";
|
|
||||||
ss << fmt::format(L"--startingDirectory \"{}{}\" ", StartingDirectory(), trailingBackslashEscape);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!TabTitle().empty())
|
if (!TabTitle().empty())
|
||||||
{
|
{
|
||||||
ss << fmt::format(L"--title \"{}\" ", TabTitle());
|
ss << fmt::format(L"--title {} ", QuoteAndEscapeCommandlineArg(TabTitle()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TabColor())
|
if (TabColor())
|
||||||
|
@ -152,7 +150,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||||
|
|
||||||
if (!ColorScheme().empty())
|
if (!ColorScheme().empty())
|
||||||
{
|
{
|
||||||
ss << fmt::format(L"--colorScheme \"{}\" ", ColorScheme());
|
ss << fmt::format(L"--colorScheme {} ", QuoteAndEscapeCommandlineArg(ColorScheme()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Commandline().empty())
|
if (!Commandline().empty())
|
||||||
|
@ -300,6 +298,10 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||||
return RS_(L"MoveFocusPreviousInOrder");
|
return RS_(L"MoveFocusPreviousInOrder");
|
||||||
case FocusDirection::First:
|
case FocusDirection::First:
|
||||||
return RS_(L"MoveFocusFirstPane");
|
return RS_(L"MoveFocusFirstPane");
|
||||||
|
case FocusDirection::Parent:
|
||||||
|
return RS_(L"MoveFocusParentPane");
|
||||||
|
case FocusDirection::Child:
|
||||||
|
return RS_(L"MoveFocusChildPane");
|
||||||
}
|
}
|
||||||
|
|
||||||
return winrt::hstring{
|
return winrt::hstring{
|
||||||
|
|
|
@ -864,6 +864,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||||
struct SetTabColorArgs : public SetTabColorArgsT<SetTabColorArgs>
|
struct SetTabColorArgs : public SetTabColorArgsT<SetTabColorArgs>
|
||||||
{
|
{
|
||||||
SetTabColorArgs() = default;
|
SetTabColorArgs() = default;
|
||||||
|
SetTabColorArgs(Windows::UI::Color tabColor) :
|
||||||
|
_TabColor{ tabColor } {}
|
||||||
ACTION_ARG(Windows::Foundation::IReference<Windows::UI::Color>, TabColor, nullptr);
|
ACTION_ARG(Windows::Foundation::IReference<Windows::UI::Color>, TabColor, nullptr);
|
||||||
|
|
||||||
static constexpr std::string_view ColorKey{ "color" };
|
static constexpr std::string_view ColorKey{ "color" };
|
||||||
|
@ -1582,6 +1584,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||||
struct RenameWindowArgs : public RenameWindowArgsT<RenameWindowArgs>
|
struct RenameWindowArgs : public RenameWindowArgsT<RenameWindowArgs>
|
||||||
{
|
{
|
||||||
RenameWindowArgs() = default;
|
RenameWindowArgs() = default;
|
||||||
|
RenameWindowArgs(winrt::hstring name) :
|
||||||
|
_Name{ name } {};
|
||||||
ACTION_ARG(winrt::hstring, Name);
|
ACTION_ARG(winrt::hstring, Name);
|
||||||
static constexpr std::string_view NameKey{ "name" };
|
static constexpr std::string_view NameKey{ "name" };
|
||||||
|
|
||||||
|
@ -1679,7 +1683,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||||
JsonUtils::SetValueForKey(json, NameKey, args->_Name);
|
JsonUtils::SetValueForKey(json, NameKey, args->_Name);
|
||||||
JsonUtils::SetValueForKey(json, DesktopKey, args->_Desktop);
|
JsonUtils::SetValueForKey(json, DesktopKey, args->_Desktop);
|
||||||
JsonUtils::SetValueForKey(json, MonitorKey, args->_Monitor);
|
JsonUtils::SetValueForKey(json, MonitorKey, args->_Monitor);
|
||||||
JsonUtils::GetValueForKey(json, DropdownDurationKey, args->_DropdownDuration);
|
JsonUtils::SetValueForKey(json, DropdownDurationKey, args->_DropdownDuration);
|
||||||
JsonUtils::SetValueForKey(json, ToggleVisibilityKey, args->_ToggleVisibility);
|
JsonUtils::SetValueForKey(json, ToggleVisibilityKey, args->_ToggleVisibility);
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
@ -1869,9 +1873,11 @@ namespace winrt::Microsoft::Terminal::Settings::Model::factory_implementation
|
||||||
BASIC_FACTORY(NewTabArgs);
|
BASIC_FACTORY(NewTabArgs);
|
||||||
BASIC_FACTORY(MoveFocusArgs);
|
BASIC_FACTORY(MoveFocusArgs);
|
||||||
BASIC_FACTORY(MovePaneArgs);
|
BASIC_FACTORY(MovePaneArgs);
|
||||||
|
BASIC_FACTORY(SetTabColorArgs);
|
||||||
BASIC_FACTORY(SwapPaneArgs);
|
BASIC_FACTORY(SwapPaneArgs);
|
||||||
BASIC_FACTORY(SplitPaneArgs);
|
BASIC_FACTORY(SplitPaneArgs);
|
||||||
BASIC_FACTORY(SetColorSchemeArgs);
|
BASIC_FACTORY(SetColorSchemeArgs);
|
||||||
|
BASIC_FACTORY(RenameWindowArgs);
|
||||||
BASIC_FACTORY(ExecuteCommandlineArgs);
|
BASIC_FACTORY(ExecuteCommandlineArgs);
|
||||||
BASIC_FACTORY(CloseOtherTabsArgs);
|
BASIC_FACTORY(CloseOtherTabsArgs);
|
||||||
BASIC_FACTORY(CloseTabsAfterArgs);
|
BASIC_FACTORY(CloseTabsAfterArgs);
|
||||||
|
|
|
@ -38,7 +38,9 @@ namespace Microsoft.Terminal.Settings.Model
|
||||||
Previous,
|
Previous,
|
||||||
PreviousInOrder,
|
PreviousInOrder,
|
||||||
NextInOrder,
|
NextInOrder,
|
||||||
First
|
First,
|
||||||
|
Parent,
|
||||||
|
Child
|
||||||
};
|
};
|
||||||
|
|
||||||
enum SplitDirection
|
enum SplitDirection
|
||||||
|
@ -213,6 +215,7 @@ namespace Microsoft.Terminal.Settings.Model
|
||||||
|
|
||||||
[default_interface] runtimeclass SetTabColorArgs : IActionArgs
|
[default_interface] runtimeclass SetTabColorArgs : IActionArgs
|
||||||
{
|
{
|
||||||
|
SetTabColorArgs(Windows.UI.Color tabColor);
|
||||||
Windows.Foundation.IReference<Windows.UI.Color> TabColor { get; };
|
Windows.Foundation.IReference<Windows.UI.Color> TabColor { get; };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -294,6 +297,7 @@ namespace Microsoft.Terminal.Settings.Model
|
||||||
|
|
||||||
[default_interface] runtimeclass RenameWindowArgs : IActionArgs
|
[default_interface] runtimeclass RenameWindowArgs : IActionArgs
|
||||||
{
|
{
|
||||||
|
RenameWindowArgs(String name);
|
||||||
String Name { get; };
|
String Name { get; };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -94,15 +94,14 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||||
static void RegisterShortcutAction(ShortcutAction shortcutAction, std::unordered_map<hstring, Model::ActionAndArgs>& list, std::unordered_set<InternalActionID>& visited)
|
static void RegisterShortcutAction(ShortcutAction shortcutAction, std::unordered_map<hstring, Model::ActionAndArgs>& list, std::unordered_set<InternalActionID>& visited)
|
||||||
{
|
{
|
||||||
const auto actionAndArgs{ make_self<ActionAndArgs>(shortcutAction) };
|
const auto actionAndArgs{ make_self<ActionAndArgs>(shortcutAction) };
|
||||||
if (actionAndArgs->Action() != ShortcutAction::Invalid)
|
/*We have a valid action.*/
|
||||||
|
/*Check if the action was already added.*/
|
||||||
|
if (visited.find(Hash(*actionAndArgs)) == visited.end())
|
||||||
{
|
{
|
||||||
/*We have a valid action.*/
|
/*This is an action that wasn't added!*/
|
||||||
/*Check if the action was already added.*/
|
/*Let's add it if it has a name.*/
|
||||||
if (visited.find(Hash(*actionAndArgs)) == visited.end())
|
if (const auto name{ actionAndArgs->GenerateName() }; !name.empty())
|
||||||
{
|
{
|
||||||
/*This is an action that wasn't added!*/
|
|
||||||
/*Let's add it.*/
|
|
||||||
const auto name{ actionAndArgs->GenerateName() };
|
|
||||||
list.insert({ name, *actionAndArgs });
|
list.insert({ name, *actionAndArgs });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue