Compare commits

...

53 Commits

Author SHA1 Message Date
Dustin L. Howett
6b35e55aef Migrate spelling-0.0.21 changes from main 2022-05-04 14:39:59 -05:00
Mike Griese
0ee30f29cb this changed nothing 2022-05-04 14:39:59 -05:00
Mike Griese
f4d9fa2e01 at least we get the hovers back, but of course, still looks dumb. 2022-05-04 13:23:32 -05:00
Mike Griese
4ae9887e3e At least this lets me move the window again 2022-05-04 13:10:54 -05:00
Mike Griese
2de5f3980d This doesn't work
The titlebars are all the wrong size. I can't make it as tall as the XAML titlebar, cause of course not. I can't get dragging to work, cause I probably commented out the load bearing part of the code. The Transparent hole I thought I made? Not transparent at all. Probably b/c I'm setting Titlebar().Background() which goes behind the hole, when I want instead a Border w/in the TitlebarControl that the BG should be applied to.

It's a disaster.
2022-05-04 12:50:16 -05:00
Mike Griese
f53fe070db more notes because existence is pain 2022-05-04 12:06:00 -05:00
Mike Griese
a5b3063e62 This seems to work but breaks snap flyouts 2022-05-04 06:50:11 -05:00
Mike Griese
6c28ba6bf3 make the code a lot cleaner 2022-05-03 15:24:03 -05:00
Mike Griese
99bc963222 this is simpler 2022-05-03 12:09:44 -05:00
Mike Griese
68d70a053b this is REALLY janky but seems to work 2022-05-03 12:04:14 -05:00
Mike Griese
3281a3a334 Merge remote-tracking branch 'origin/main' into dev/migrie/fhl/theming-2022-prototype 2022-05-03 09:33:23 -05:00
Mike Griese
24f945a7f5 Merge remote-tracking branch 'origin/main' into dev/migrie/fhl/theming-2022-prototype 2022-04-29 09:05:09 -05:00
Mike Griese
03da3b7cc8 runformat 2022-04-28 05:47:27 -05:00
Mike Griese
9b9a6440b5 spell 2022-04-28 05:29:27 -05:00
Mike Griese
a1ea0fdc4f forgot you 2022-04-28 05:27:00 -05:00
Mike Griese
fd2dd3a1b5 cleanup for the review 2022-04-27 16:38:49 -05:00
Mike Griese
446e17b833 Merge remote-tracking branch 'origin/main' into dev/migrie/fhl/theming-2022-prototype 2022-04-27 16:07:42 -05:00
Mike Griese
bc8bb8eb15 more comments 2022-04-27 16:05:06 -05:00
Mike Griese
e2318b4dad This is horrifying 2022-04-27 14:40:03 -05:00
Mike Griese
b6b9aeaaaa Use better display names 2022-04-27 13:01:26 -05:00
Mike Griese
a57187b93c include the themes 2022-04-27 12:33:41 -05:00
Mike Griese
cfb99d9720 Change theme with the SUI and actually have it persist 2022-04-27 12:17:50 -05:00
Mike Griese
9bebb74aef Some settings saving roundtripping bugs 2022-04-27 12:08:41 -05:00
Mike Griese
39b6fddea4 Some minor todos 2022-04-26 15:58:14 -05:00
Mike Griese
01d69072ad I think that's everything 2022-04-26 15:46:03 -05:00
Mike Griese
de22df01e5 switches when a tab does, not the pane 2022-04-26 15:01:58 -05:00
Mike Griese
606db76010 this is like 99% of the work here 2022-04-26 14:40:08 -05:00
Mike Griese
724360313f hey this is easier 2022-04-26 13:57:41 -05:00
Mike Griese
df0efffd8e stragglers 2022-04-26 12:35:47 -05:00
Mike Griese
7fcfda36d1 wow 2022-04-26 12:30:44 -05:00
Mike Griese
fe26114610 better, better, 2022-04-26 12:11:40 -05:00
Mike Griese
5081118bbb This is horrifying and yet I'm totally shipping it. Move the objects to be sub-properties of the Theme 2022-04-26 12:03:30 -05:00
Mike Griese
4f42661488 Lookup themes from a list of themes, use that one to style the window 2022-04-26 11:06:04 -05:00
Mike Griese
a7ce8603ea cleanup, works on start and when unset 2022-04-26 09:37:06 -05:00
Mike Griese
99dc75d872 this actually works now. Remember kids, break statements in switch/cases are NOT optional 2022-04-26 09:18:45 -05:00
Mike Griese
e22046fb42 accept accent color as a ThemeColor 2022-04-26 06:34:51 -05:00
Mike Griese
1d0a5d747d Merge remote-tracking branch 'origin/dev/migrie/titebar-colors' into dev/migrie/fhl/theming-2022-prototype 2022-04-26 05:59:48 -05:00
Mike Griese
03211c82cb Merge remote-tracking branch 'origin/main' into dev/migrie/fhl/theming-2022-prototype 2022-04-26 05:38:56 -05:00
Mike Griese
ac49459dde change color based on if the window is activated or now 2022-04-26 04:52:04 -05:00
Mike Griese
cd0012a6b1 guess what, it works 2022-04-25 10:04:34 -05:00
Mike Griese
f92724dfb0 We can't be clever here. Just make an observable property and slam the brush in there 2022-04-25 09:25:33 -05:00
Mike Griese
44112fcfa6 really, no good progress here. It's rough 2022-03-28 11:04:45 -05:00
Mike Griese
9eff0a2e28 i feel like I'm getting closer 2022-03-25 11:03:59 -05:00
Mike Griese
ee9333af13 A pile of dead ends.
https://stackoverflow.com/questions/64694722/changing-themeresources-dynamically-in-uwp

That post looked SUPER promising. Problem is though, I CANNOT for the life of me
get that to work. Like, I can't get anything to `{Binding Brush, Mode=TwoWay,
Source={StaticResource TerminalBackground}}` to the `TerminalBackground` thing I
made there. I thought that was so clever.

I wanted an easy way to just change the value of a resource and have it update
the Titlebar, but since the Titlebar isn't a child of the TerminalPage, and this
binding thing didn't work, I think I'm at a dead end.
2022-03-25 10:45:18 -05:00
Mike Griese
01f07be64f okay so you can't change a solid brush to an acylic one at runtime 2022-03-25 05:45:52 -05:00
Mike Griese
c555e6efca this did seem to work, but will it work for acrylic? 2022-03-25 05:29:11 -05:00
Mike Griese
9670d139a6 mica works, but the titlebar looks DUMB 2022-03-24 11:25:49 -05:00
Mike Griese
84805f59aa dumbly accept alpha channel in colors 2022-03-24 10:54:59 -05:00
Mike Griese
9627483f56 okay so i bet that resource changed. Whatever, we'll work with it. 2022-03-24 10:41:00 -05:00
Mike Griese
b4cd7b3d71 this is better. Apphost is gonna need to be involved anyways so fuck it 2022-03-24 10:23:10 -05:00
Mike Griese
00c135b4d4 on reload, this changes the BG of the titlebar, but not the tab view 2022-03-24 10:15:12 -05:00
Mike Griese
7e0ae358fb this fixes the App bits as well 2022-03-24 06:45:52 -05:00
Mike Griese
15e4fd9be9 Settings project builds at least 2022-03-24 06:31:38 -05:00
51 changed files with 2228 additions and 1070 deletions

15
.github/actions/spelling/README.md vendored Normal file
View File

@@ -0,0 +1,15 @@
# check-spelling/check-spelling configuration
File | Purpose | Format | Info
-|-|-|-
[allow/*.txt](allow/) | Add words to the dictionary | one word per line (only letters and `'`s allowed) | [allow](https://github.com/check-spelling/check-spelling/wiki/Configuration#allow)
[reject.txt](reject.txt) | Remove words from the dictionary (after allow) | grep pattern matching whole dictionary words | [reject](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-reject)
[excludes.txt](excludes.txt) | Files to ignore entirely | perl regular expression | [excludes](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-excludes)
[patterns/*.txt](patterns/) | Patterns to ignore from checked lines | perl regular expression (order matters, first match wins) | [patterns](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-patterns)
[candidate.patterns](candidate.patterns) | Patterns that might be worth adding to [patterns.txt](patterns.txt) | perl regular expression with optional comment block introductions (all matches will be suggested) | [candidates](https://github.com/check-spelling/check-spelling/wiki/Feature:-Suggest-patterns)
[line_forbidden.patterns](line_forbidden.patterns) | Patterns to flag in checked lines | perl regular expression (order matters, first match wins) | [patterns](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-patterns)
[expect/*.txt](expect.txt) | Expected words that aren't in the dictionary | one word per line (sorted, alphabetically) | [expect](https://github.com/check-spelling/check-spelling/wiki/Configuration#expect)
[advice.md](advice.md) | Supplement for GitHub comment when unrecognized words are found | GitHub Markdown | [advice](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-advice)
Note: you can replace any of these files with a directory by the same name (minus the suffix)
and then include multiple files inside that directory (with that suffix) to merge multiple files together.

View File

@@ -1,4 +1,4 @@
<!-- markdownlint-disable MD033 MD041 -->
<!-- See https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-advice --> <!-- markdownlint-disable MD033 MD041 -->
<details>
<summary>
:pencil2: Contributor please read this
@@ -6,7 +6,7 @@
By default the command suggestion will generate a file named based on your commit. That's generally ok as long as you add the file to your commit. Someone can reorganize it later.
:warning: The command is written for posix shells. You can copy the contents of each `perl` command excluding the outer `'` marks and dropping any `'"`/`"'` quotation mark pairs into a file and then run `perl file.pl` from the root of the repository to run the code. Alternatively, you can manually insert the items...
:warning: The command is written for posix shells. If it doesn't work for you, you can manually _add_ (one word per line) / _remove_ items to `expect.txt` and the `excludes.txt` files.
If the listed items are:
@@ -20,31 +20,29 @@ See the `README.md` in each directory for more information.
:microscope: You can test your commits **without** *appending* to a PR by creating a new branch with that extra change and pushing it to your fork. The [check-spelling](https://github.com/marketplace/actions/check-spelling) action will run in response to your **push** -- it doesn't require an open pull request. By using such a branch, you can limit the number of typos your peers see you make. :wink:
<details><summary>:clamp: If you see a bunch of garbage</summary>
If it relates to a ...
<details><summary>well-formed pattern</summary>
<details><summary>If the flagged items are :exploding_head: false positives</summary>
See if there's a [pattern](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples:-patterns) that would match it.
If items relate to a ...
* binary file (or some other file you wouldn't want to check at all).
If not, try writing one and adding it to a `patterns/{file}.txt`.
Please add a file path to the `excludes.txt` file matching the containing file.
Patterns are Perl 5 Regular Expressions - you can [test](
https://www.regexplanet.com/advanced/perl/) yours before committing to verify it will match your lines.
Note that patterns can't match multiline strings.
</details>
<details><summary>binary-ish string</summary>
Please add a file path to the `excludes.txt` file instead of just accepting the garbage.
File paths are Perl 5 Regular Expressions - you can [test](
File paths are Perl 5 Regular Expressions - you can [test](
https://www.regexplanet.com/advanced/perl/) yours before committing to verify it will match your files.
`^` refers to the file's path from the root of the repository, so `^README\.md$` would exclude [README.md](
`^` refers to the file's path from the root of the repository, so `^README\.md$` would exclude [README.md](
../tree/HEAD/README.md) (on whichever branch you're using).
</details>
* well-formed pattern.
If you can write a [pattern](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples:-patterns) that would match it,
try adding it to the `patterns.txt` file.
Patterns are Perl 5 Regular Expressions - you can [test](
https://www.regexplanet.com/advanced/perl/) yours before committing to verify it will match your lines.
Note that patterns can't match multiline strings.
</details>
</details>

View File

@@ -1,20 +1,21 @@
admins
apc
allcolors
Apc
bsd
apc
breadcrumb
breadcrumbs
bsd
calt
CMMI
ccmp
changelog
clickable
clig
CMMI
copyable
cybersecurity
dalet
dcs
Dcs
dcs
dialytika
dje
downside
@@ -26,36 +27,43 @@ EDDC
Enum'd
Fitt
formattings
FTCS
ftp
fvar
gantt
gcc
geeksforgeeks
ghe
github
gje
godbolt
hostname
hostnames
https
hyperlink
hyperlinking
hyperlinks
iconify
img
inlined
It'd
kje
libfuzzer
libuv
liga
lje
Llast
llvm
Lmid
locl
lol
lorem
Lorigin
maxed
minimalistic
mkmk
mnt
mru
noreply
nje
noreply
ogonek
@@ -76,13 +84,16 @@ runtimes
shcha
slnt
Sos
ssh
timeline
timelines
timestamped
TLDR
tokenizes
tonos
toolset
tshe
ubuntu
uiatextrange
UIs
und
@@ -91,6 +102,7 @@ versioned
vsdevcmd
We'd
wildcards
XBox
YBox
yeru
zhe
allcolors

View File

@@ -5,6 +5,7 @@ aclapi
alignas
alignof
APPLYTOSUBMENUS
appxrecipe
bitfield
bitfields
BUILDBRANCH
@@ -14,6 +15,7 @@ BYCOMMAND
BYPOSITION
charconv
CLASSNOTAVAILABLE
CLOSEAPP
cmdletbinding
COLORPROPERTY
colspan
@@ -28,9 +30,14 @@ dataobject
dcomp
DERR
dlldata
DNE
DONTADDTORECENT
DWMSBT
DWMWA
DWMWA
DWORDLONG
endfor
ENDSESSION
enumset
environstrings
EXPCMDFLAGS
@@ -70,6 +77,7 @@ IDirect
IExplorer
IFACEMETHOD
IFile
IGraphics
IInheritable
IMap
IMonarch
@@ -84,6 +92,7 @@ istream
IStringable
ITab
ITaskbar
itow
IUri
IVirtual
KEYSELECT
@@ -95,12 +104,15 @@ lround
Lsa
lsass
LSHIFT
LTGRAY
MAINWINDOW
memchr
memicmp
MENUCOMMAND
MENUDATA
MENUITEMINFOW
MENUINFO
MENUITEMINFOW
mmeapi
MOUSELEAVE
mov
mptt
@@ -136,16 +148,18 @@ OUTLINETEXTMETRICW
overridable
PACL
PAGESCROLL
PATINVERT
PEXPLICIT
PICKFOLDERS
pmr
ptstr
QUERYENDSESSION
rcx
REGCLS
RETURNCMD
rfind
roundf
ROOTOWNER
roundf
RSHIFT
SACL
schandle
@@ -175,6 +189,8 @@ Stubless
Subheader
Subpage
syscall
SYSTEMBACKDROP
TABROW
TASKBARCREATED
TBPF
THEMECHANGED
@@ -194,6 +210,8 @@ UOI
UPDATEINIFILE
userenv
USEROBJECTFLAGS
Viewbox
virtualalloc
wcsstr
wcstoui
winmain

View File

@@ -69,6 +69,8 @@ Rincewind
rprichard
Schoonover
shadertoy
Shomnipotence
simioni
Somuah
sonph
sonpham

View File

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

View File

@@ -1,28 +1,39 @@
# See https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples:-excludes
(?:(?i)\.png$)
(?:^|/)(?i)COPYRIGHT
(?:^|/)(?i)LICEN[CS]E
(?:^|/)3rdparty/
(?:^|/)dirs$
(?:^|/)go\.mod$
(?:^|/)go\.sum$
(?:^|/)package-lock\.json$
(?:^|/)package(?:-lock|)\.json$
(?:^|/)sources(?:|\.dep)$
SUMS$
(?:^|/)vendor/
\.a$
\.ai$
\.avi$
\.bmp$
\.bz2$
\.cer$
\.class$
\.crl$
\.crt$
\.csr$
\.dll$
\.docx?$
\.drawio$
\.DS_Store$
\.eot$
\.eps$
\.exe$
\.gif$
\.gitattributes$
\.graffle$
\.gz$
\.icns$
\.ico$
\.jar$
\.jks$
\.jpeg$
\.jpg$
\.key$
@@ -30,28 +41,52 @@ SUMS$
\.lock$
\.map$
\.min\..
\.mod$
\.mp3$
\.mp4$
\.o$
\.ocf$
\.otf$
\.pbxproj$
\.pdf$
\.pem$
\.png$
\.psd$
\.pyc$
\.runsettings$
\.s$
\.sig$
\.so$
\.svg$
\.svgz$
\.svgz?$
\.tar$
\.tgz$
\.tiff?$
\.ttf$
\.vsdx$
\.wav$
\.webm$
\.webp$
\.woff
\.woff2?$
\.xcf$
\.xls
\.xlsx?$
\.xpm$
\.yml$
\.zip$
^\.github/actions/spelling/
^\.github/fabricbot.json$
^\.gitignore$
^\Q.git-blame-ignore-revs\E$
^\Q.github/workflows/spelling.yml\E$
^\Qdoc/reference/windows-terminal-logo.ans\E$
^\Qsamples/ConPTY/EchoCon/EchoCon/EchoCon.vcxproj.filters\E$
^\Qsrc/host/exe/Host.EXE.vcxproj.filters\E$
^\Qsrc/host/ft_host/chafa.txt\E$
^\Qsrc/tools/closetest/CloseTest.vcxproj.filters\E$
^\XamlStyler.json$
^build/config/
^consolegit2gitfilters\.json$
^dep/
@@ -78,6 +113,5 @@ SUMS$
^src/tools/U8U16Test/(?:fr|ru|zh)\.txt$
^src/types/ut_types/UtilsTests.cpp$
^tools/ReleaseEngineering/ServicingPipeline.ps1$
^\.github/actions/spelling/
^\.gitignore$
^\XamlStyler.json$
ignore$
SUMS$

View File

@@ -5,26 +5,19 @@ AAAAAABBBBBBCCC
AAAAABBBBBBCCC
abcd
abcd
abcde
abcdef
ABCDEFG
ABCDEFGH
ABCDEFGHIJ
abcdefghijk
ABCDEFGHIJKLMNO
abcdefghijklmnop
ABCDEFGHIJKLMNOPQRST
abcdefghijklmnopqrstuvwxyz
ABCG
ABE
abf
BBBBB
BBBBBBBB
BBBBBBBBBBBBBBDDDD
BBBBBCCC
BBBBCCCCC
BBGGRR
CCE
EFG
EFGh
QQQQQQQQQQABCDEFGHIJ
@@ -33,7 +26,6 @@ QQQQQQQQQQABCDEFGHIJKLMNOPQRSTQQQQQQQQQQ
QQQQQQQQQQABCDEFGHIJPQRSTQQQQQQQQQQ
qrstuvwxyz
qwerty
QWERTYUIOP
qwertyuiopasdfg
YYYYYYYDDDDDDDDDDD
ZAAZZ

File diff suppressed because it is too large Load Diff

View File

@@ -1,29 +1,6 @@
http
www
easyrgb
php
ecma
rapidtables
WCAG
freedesktop
ycombinator
robertelder
kovidgoyal
leonerd
fixterms
winui
appshellintegration
mdtauk
cppreference
gfycat
Guake
azurewebsites
askubuntu
dostips
viewtopic
rosettacode
Rexx
tldp
HOWTO
uwspace
uwaterloo

View File

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

View File

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

View File

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

View File

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

View File

@@ -367,11 +367,12 @@ namespace winrt::TerminalApp::implementation
// details here, but it does have the desired effect.
// It's not enough to set the theme on the dialog alone.
auto themingLambda{ [this](const Windows::Foundation::IInspectable& sender, const RoutedEventArgs&) {
auto theme{ _settings.GlobalSettings().Theme() };
auto theme{ _settings.GlobalSettings().CurrentTheme() };
auto requestedTheme{ theme.Window().RequestedTheme() };
auto element{ sender.try_as<winrt::Windows::UI::Xaml::FrameworkElement>() };
while (element)
{
element.RequestedTheme(theme);
element.RequestedTheme(requestedTheme);
element = element.Parent().try_as<winrt::Windows::UI::Xaml::FrameworkElement>();
}
} };
@@ -743,7 +744,7 @@ namespace winrt::TerminalApp::implementation
LoadSettings();
}
return _settings.GlobalSettings().Theme();
return _settings.GlobalSettings().CurrentTheme().Window().RequestedTheme();
}
bool AppLogic::GetShowTabsInTitlebar()
@@ -964,7 +965,7 @@ namespace winrt::TerminalApp::implementation
void AppLogic::_RefreshThemeRoutine()
{
_ApplyTheme(_settings.GlobalSettings().Theme());
_ApplyTheme(_settings.GlobalSettings().CurrentTheme().Window().RequestedTheme());
}
// Function Description:
@@ -1219,6 +1220,19 @@ namespace winrt::TerminalApp::implementation
return {};
}
winrt::Windows::UI::Xaml::Media::Brush AppLogic::TitlebarBrush()
{
if (_root)
{
return _root->TitlebarBrush();
}
return { nullptr };
}
void AppLogic::WindowActivated(const bool activated)
{
_root->WindowActivated(activated);
}
bool AppLogic::HasCommandlineArguments() const noexcept
{
return _hasCommandLineArguments;
@@ -1645,4 +1659,15 @@ namespace winrt::TerminalApp::implementation
{
return _settings.GlobalSettings().ShowTitleInTitlebar();
}
Microsoft::Terminal::Settings::Model::Theme AppLogic::Theme()
{
if (!_loadedInitialSettings)
{
// Load settings if we haven't already
LoadSettings();
}
return _settings.GlobalSettings().CurrentTheme();
}
}

View File

@@ -117,6 +117,8 @@ namespace winrt::TerminalApp::implementation
void WindowVisibilityChanged(const bool showOrHide);
winrt::TerminalApp::TaskbarState TaskbarState();
winrt::Windows::UI::Xaml::Media::Brush TitlebarBrush();
void WindowActivated(const bool activated);
bool GetMinimizeToNotificationArea();
bool GetAlwaysShowNotificationIcon();
@@ -127,7 +129,13 @@ namespace winrt::TerminalApp::implementation
Windows::Foundation::Collections::IMapView<Microsoft::Terminal::Control::KeyChord, Microsoft::Terminal::Settings::Model::Command> GlobalHotkeys();
Microsoft::Terminal::Settings::Model::Theme Theme();
// -------------------------------- WinRT Events ---------------------------------
// PropertyChanged is surprisingly not a typed event, so we'll define that one manually.
winrt::event_token PropertyChanged(Windows::UI::Xaml::Data::PropertyChangedEventHandler const& handler) { return _root->PropertyChanged(handler); }
void PropertyChanged(winrt::event_token const& token) { _root->PropertyChanged(token); }
TYPED_EVENT(RequestedThemeChanged, winrt::Windows::Foundation::IInspectable, winrt::Windows::UI::Xaml::ElementTheme);
TYPED_EVENT(SettingsChanged, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
TYPED_EVENT(SystemMenuChangeRequested, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::SystemMenuChangeArgs);

View File

@@ -35,7 +35,7 @@ namespace TerminalApp
// See IDialogPresenter and TerminalPage's DialogPresenter for more
// information.
[default_interface] runtimeclass AppLogic : IDirectKeyListener, IDialogPresenter
[default_interface] runtimeclass AppLogic : IDirectKeyListener, IDialogPresenter, Windows.UI.Xaml.Data.INotifyPropertyChanged
{
AppLogic();
@@ -94,6 +94,8 @@ namespace TerminalApp
void WindowVisibilityChanged(Boolean showOrHide);
TaskbarState TaskbarState{ get; };
Windows.UI.Xaml.Media.Brush TitlebarBrush { get; };
void WindowActivated(Boolean activated);
Boolean ShouldUsePersistedLayout();
Boolean ShouldImmediatelyHandoffToElevated();
@@ -105,6 +107,8 @@ namespace TerminalApp
Boolean GetAlwaysShowNotificationIcon();
Boolean GetShowTitleInTitlebar();
Microsoft.Terminal.Settings.Model.Theme Theme { get; };
FindTargetWindowResult FindTargetWindow(String[] args);
Windows.Foundation.Collections.IMapView<Microsoft.Terminal.Control.KeyChord, Microsoft.Terminal.Settings.Model.Command> GlobalHotkeys();

View File

@@ -3,8 +3,6 @@
#pragma once
#include "winrt/Microsoft.UI.Xaml.Controls.h"
#include "HighlightedTextSegment.g.h"
#include "HighlightedText.g.h"

View File

@@ -148,6 +148,8 @@ namespace winrt::TerminalApp::implementation
// Possibly update the icon of the tab.
page->_UpdateTabIcon(*tab);
page->_updateTabRowColors();
// Update the taskbar progress as well. We'll raise our own
// SetTaskbarProgress event here, to get tell the hosting
// application to re-query this value from us.
@@ -909,6 +911,8 @@ namespace winrt::TerminalApp::implementation
_TitleChangedHandlers(*this, tab.Title());
}
_updateTabRowColors();
auto tab_impl = _GetTerminalTabImpl(tab);
if (tab_impl)
{

View File

@@ -160,43 +160,6 @@ namespace winrt::TerminalApp::implementation
const auto isElevated = IsElevated();
if (_settings.GlobalSettings().UseAcrylicInTabRow())
{
const auto res = Application::Current().Resources();
const auto lightKey = winrt::box_value(L"Light");
const auto darkKey = winrt::box_value(L"Dark");
const auto tabViewBackgroundKey = winrt::box_value(L"TabViewBackground");
for (const auto& dictionary : res.MergedDictionaries())
{
// Don't change MUX resources
if (dictionary.Source())
{
continue;
}
for (const auto& kvPair : dictionary.ThemeDictionaries())
{
const auto themeDictionary = kvPair.Value().as<winrt::Windows::UI::Xaml::ResourceDictionary>();
if (themeDictionary.HasKey(tabViewBackgroundKey))
{
const auto backgroundSolidBrush = themeDictionary.Lookup(tabViewBackgroundKey).as<Media::SolidColorBrush>();
const til::color backgroundColor = backgroundSolidBrush.Color();
const auto acrylicBrush = Media::AcrylicBrush();
acrylicBrush.BackgroundSource(Media::AcrylicBackgroundSource::HostBackdrop);
acrylicBrush.FallbackColor(backgroundColor);
acrylicBrush.TintColor(backgroundColor);
acrylicBrush.TintOpacity(0.5);
themeDictionary.Insert(tabViewBackgroundKey, acrylicBrush);
}
}
}
}
_tabRow.PointerMoved({ get_weak(), &TerminalPage::_RestorePointerCursorHandler });
_tabView.CanReorderTabs(!isElevated);
_tabView.CanDragTabs(!isElevated);
@@ -219,6 +182,7 @@ namespace winrt::TerminalApp::implementation
// Inform the host that our titlebar content has changed.
_SetTitleBarContentHandlers(*this, _tabRow);
}
_updateTabRowColors();
// Hookup our event handlers to the ShortcutActionDispatch
_RegisterActionCallbacks();
@@ -1430,6 +1394,17 @@ namespace winrt::TerminalApp::implementation
term.ConnectionStateChanged({ get_weak(), &TerminalPage::_ConnectionStateChangedHandler });
auto weakThis{ get_weak() };
term.PropertyChanged([weakThis](auto& /*sender*/, auto& e) {
if (auto page{ weakThis.get() })
{
if (e.PropertyName() == L"BackgroundBrush")
{
page->_updateTabRowColors();
}
}
});
term.ShowWindowChanged({ get_weak(), &TerminalPage::_ShowWindowChangedHandler });
}
@@ -1469,37 +1444,9 @@ namespace winrt::TerminalApp::implementation
}
});
// react on color changed events
hostingTab.ColorSelected([weakTab, weakThis](auto&& color) {
auto page{ weakThis.get() };
auto tab{ weakTab.get() };
if (page && tab && (tab->FocusState() != FocusState::Unfocused))
{
page->_SetNonClientAreaColors(color);
}
});
hostingTab.ColorCleared([weakTab, weakThis]() {
auto page{ weakThis.get() };
auto tab{ weakTab.get() };
if (page && tab && (tab->FocusState() != FocusState::Unfocused))
{
page->_ClearNonClientAreaColors();
}
});
// Add an event handler for when the terminal or tab wants to set a
// progress indicator on the taskbar
hostingTab.TaskbarProgressChanged({ get_weak(), &TerminalPage::_SetTaskbarProgressHandler });
// TODO GH#3327: Once we support colorizing the NewTab button based on
// the color of the tab, we'll want to make sure to call
// _ClearNewTabButtonColor here, to reset it to the default (for the
// newly created tab).
// remove any colors left by other colored tabs
// _ClearNewTabButtonColor();
}
// Method Description:
@@ -2697,6 +2644,13 @@ namespace winrt::TerminalApp::implementation
WUX::Media::Animation::Timeline::AllowDependentAnimations(!_settings.GlobalSettings().DisableAnimations());
_tabRow.ShowElevationShield(IsElevated() && _settings.GlobalSettings().ShowAdminShield());
Media::SolidColorBrush transparent{ Windows::UI::Colors::Transparent() };
_tabView.Background(transparent);
////////////////////////////////////////////////////////////////////////
// Begin Theme handling
_updateTabRowColors();
}
// This is a helper to aid in sorting commands by their `Name`s, alphabetically.
@@ -3081,32 +3035,6 @@ namespace winrt::TerminalApp::implementation
_newTabButton.Foreground(foregroundBrush);
}
// Method Description:
// - Sets the tab split button color when a new tab color is selected
// - This method could also set the color of the title bar and tab row
// in the future
// Arguments:
// - selectedTabColor: The color of the newly selected tab
// Return Value:
// - <none>
void TerminalPage::_SetNonClientAreaColors(const Windows::UI::Color& /*selectedTabColor*/)
{
// TODO GH#3327: Look at what to do with the NC area when we have XAML theming
}
// Method Description:
// - Clears the tab split button color when the tab's color is cleared
// - This method could also clear the color of the title bar and tab row
// in the future
// Arguments:
// - <none>
// Return Value:
// - <none>
void TerminalPage::_ClearNonClientAreaColors()
{
// TODO GH#3327: Look at what to do with the NC area when we have XAML theming
}
// Function Description:
// - This is a helper method to get the commandline out of a
// ExecuteCommandline action, break it into subcommands, and attempt to
@@ -3507,10 +3435,11 @@ namespace winrt::TerminalApp::implementation
// - <none>
void TerminalPage::_UpdateTeachingTipTheme(winrt::Windows::UI::Xaml::FrameworkElement element)
{
auto theme{ _settings.GlobalSettings().Theme() };
auto theme{ _settings.GlobalSettings().CurrentTheme() };
auto requestedTheme{ theme.Window().RequestedTheme() };
while (element)
{
element.RequestedTheme(theme);
element.RequestedTheme(requestedTheme);
element = element.Parent().try_as<winrt::Windows::UI::Xaml::FrameworkElement>();
}
}
@@ -4014,4 +3943,121 @@ namespace winrt::TerminalApp::implementation
applicationState.DismissedMessages(std::move(messages));
}
void TerminalPage::_updateTabRowColors()
{
if (_settings == nullptr)
{
return;
}
const auto theme = _settings.GlobalSettings().CurrentTheme();
auto requestedTheme{ theme.Window().RequestedTheme() };
const auto res = Application::Current().Resources();
// XAML Hacks:
//
// the App is always in the OS theme, so the
// App::Current().Resources() lookup will always get the value for the
// OS theme, not the requested theme.
//
// This helper allows us to instead lookup the value of a resource
// specified by `key` for the given `requestedTheme`, from the
// dictionaries in App.xaml. Make sure the value is actually there!
// Otherwise this'll throw like any other Lookup for a resource that
// isn't there.
static const auto lookup = [](auto& res, auto& requestedTheme, auto& key) {
// You want the Default version of the resource? Great, the App is
// always in the OS theme. Just look it up and be done.
if (requestedTheme == ElementTheme::Default)
{
return res.Lookup(key);
}
static const auto lightKey = winrt::box_value(L"Light");
static const auto darkKey = winrt::box_value(L"Dark");
// There isn't an ElementTheme::HighContrast.
auto requestedThemeKey = requestedTheme == ElementTheme::Dark ? darkKey : lightKey;
for (const auto& dictionary : res.MergedDictionaries())
{
// Don't look in the MUX resources. They come first. A person
// with more patience than me may find a way to look through our
// dictionaries first, then the MUX ones, but that's not needed
// currently
if (dictionary.Source())
{
continue;
}
// Look through the theme dictionaries we defined:
for (const auto& [dictionaryKey, dict] : dictionary.ThemeDictionaries())
{
// Does the key for this dict match the theme we're looking for?
if (winrt::unbox_value<winrt::hstring>(dictionaryKey) !=
winrt::unbox_value<winrt::hstring>(requestedThemeKey))
{
// No? skip it.
continue;
}
// Look for the requested resource in this dict.
const auto themeDictionary = dict.as<winrt::Windows::UI::Xaml::ResourceDictionary>();
if (themeDictionary.HasKey(key))
{
return themeDictionary.Lookup(key);
}
}
}
// We didn't find it in the requested dict, fall back to the default dictionary.
return res.Lookup(key);
};
// Use our helper to lookup the theme-aware version of the resource.
const auto tabViewBackgroundKey = winrt::box_value(L"TabViewBackground");
const auto backgroundSolidBrush = lookup(res, requestedTheme, tabViewBackgroundKey).as<Media::SolidColorBrush>();
til::color bgColor = backgroundSolidBrush.Color();
if (_settings.GlobalSettings().UseAcrylicInTabRow())
{
const til::color backgroundColor = backgroundSolidBrush.Color();
const auto acrylicBrush = Media::AcrylicBrush();
acrylicBrush.BackgroundSource(Media::AcrylicBackgroundSource::HostBackdrop);
acrylicBrush.FallbackColor(backgroundColor);
acrylicBrush.TintColor(backgroundColor);
acrylicBrush.TintOpacity(0.5);
TitlebarBrush(acrylicBrush);
bgColor = backgroundColor;
}
else if (theme.TabRow() && theme.TabRow().Background())
{
const auto tabRowBg = theme.TabRow().Background();
const auto terminalBrush = [this]() -> Media::Brush { if(const auto& control{_GetActiveControl()}){ return control.BackgroundBrush(); } return nullptr; }();
const auto themeBrush{ tabRowBg.Evaluate(res, terminalBrush, true) };
bgColor = ThemeColor::ColorFromBrush(themeBrush);
TitlebarBrush(themeBrush);
}
else
{
// Nothing was set in the theme - fall back to our original `TabViewBackground` color.
TitlebarBrush(backgroundSolidBrush);
}
_tabRow.Background(TitlebarBrush());
// Update the new tab button to have better contrast with the new color.
// In theory, it would be convenient to also change these for the
// inactive tabs as well, but we're leaving that as a follow up.
_SetNewTabButtonColor(bgColor, bgColor);
}
void TerminalPage::WindowActivated(const bool activated)
{
// Stash if we're activated. Use that when we reload
// the settings, change active panes, etc.
_activated = activated;
_updateTabRowColors();
}
}

View File

@@ -134,6 +134,7 @@ namespace winrt::TerminalApp::implementation
bool IsElevated() const noexcept;
void OpenSettingsUI();
void WindowActivated(const bool activated);
WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);
@@ -157,6 +158,8 @@ namespace winrt::TerminalApp::implementation
TYPED_EVENT(QuitRequested, IInspectable, IInspectable);
TYPED_EVENT(ShowWindowChanged, IInspectable, winrt::Microsoft::Terminal::Control::ShowWindowArgs)
WINRT_OBSERVABLE_PROPERTY(winrt::Windows::UI::Xaml::Media::Brush, TitlebarBrush, _PropertyChangedHandlers, nullptr);
private:
friend struct TerminalPageT<TerminalPage>; // for Xaml to bind events
std::optional<HWND> _hostingHwnd;
@@ -196,6 +199,8 @@ namespace winrt::TerminalApp::implementation
std::optional<int> _rearrangeFrom{};
std::optional<int> _rearrangeTo{};
bool _removing{ false };
bool _activated{ false };
bool _visible{ true };
std::vector<std::vector<Microsoft::Terminal::Settings::Model::ActionAndArgs>> _previouslyClosedPanesAndTabs{};
@@ -383,8 +388,6 @@ namespace winrt::TerminalApp::implementation
void _RefreshUIForSettingsReload();
void _SetNonClientAreaColors(const Windows::UI::Color& selectedTabColor);
void _ClearNonClientAreaColors();
void _SetNewTabButtonColor(const Windows::UI::Color& color, const Windows::UI::Color& accentColor);
void _ClearNewTabButtonColor();
@@ -442,6 +445,8 @@ namespace winrt::TerminalApp::implementation
static bool _IsMessageDismissed(const winrt::Microsoft::Terminal::Settings::Model::InfoBarMessage& message);
static void _DismissMessage(const winrt::Microsoft::Terminal::Settings::Model::InfoBarMessage& message);
void _updateTabRowColors();
winrt::fire_and_forget _ShowWindowChangedHandler(const IInspectable sender, const winrt::Microsoft::Terminal::Control::ShowWindowArgs args);
#pragma region ActionHandlers

View File

@@ -45,6 +45,9 @@ namespace TerminalApp
TaskbarState TaskbarState{ get; };
Windows.UI.Xaml.Media.Brush TitlebarBrush { get; };
void WindowActivated(Boolean activated);
event Windows.Foundation.TypedEventHandler<Object, String> TitleChanged;
event Windows.Foundation.TypedEventHandler<Object, LastTabClosedEventArgs> LastTabClosed;
event Windows.Foundation.TypedEventHandler<Object, Windows.UI.Xaml.UIElement> SetTitleBarContent;

View File

@@ -17,17 +17,17 @@ namespace winrt::TerminalApp::implementation
{
InitializeComponent();
// Register our event handlers on the MMC buttons.
MinMaxCloseControl().MinimizeClick({ this, &TitlebarControl::Minimize_Click });
MinMaxCloseControl().MaximizeClick({ this, &TitlebarControl::Maximize_Click });
MinMaxCloseControl().CloseClick({ this, &TitlebarControl::Close_Click });
// // Register our event handlers on the MMC buttons.
// MinMaxCloseControl().MinimizeClick({ this, &TitlebarControl::Minimize_Click });
// MinMaxCloseControl().MaximizeClick({ this, &TitlebarControl::Maximize_Click });
// MinMaxCloseControl().CloseClick({ this, &TitlebarControl::Close_Click });
}
double TitlebarControl::CaptionButtonWidth()
{
// Divide by three, since we know there are only three buttons. When
// Windows 12 comes along and adds another, we can update this /s
static auto width{ MinMaxCloseControl().ActualWidth() / 3.0 };
static auto width{ CaptionButtonSpace().ActualWidth() / 3.0 };
return width;
}
@@ -45,7 +45,7 @@ namespace winrt::TerminalApp::implementation
const Windows::UI::Xaml::SizeChangedEventArgs& /*e*/)
{
const auto windowWidth = ActualWidth();
const auto minMaxCloseWidth = MinMaxCloseControl().ActualWidth();
const auto minMaxCloseWidth = CaptionButtonSpace().ActualWidth();
const auto dragBarMinWidth = DragBar().MinWidth();
const auto maxWidth = windowWidth - minMaxCloseWidth - dragBarMinWidth;
// Only set our MaxWidth if it's greater than 0. Setting it to a
@@ -98,20 +98,62 @@ namespace winrt::TerminalApp::implementation
void TitlebarControl::SetWindowVisualState(WindowVisualState visualState)
{
MinMaxCloseControl().SetWindowVisualState(visualState);
// MinMaxCloseControl().SetWindowVisualState(visualState);
// Look up the heights we should use for the caption buttons from our
// XAML resources. "CaptionButtonHeightWindowed" and
// "CaptionButtonHeightMaximized" define the size we should use for the
// caption buttons height for the windowed and maximized states,
// respectively.
//
// use C++11 magic statics to make sure we only do this once.
static auto heights = [this]() {
const auto res = Resources();
const auto windowedHeightKey = winrt::box_value(L"CaptionButtonHeightWindowed");
const auto maximizedHeightKey = winrt::box_value(L"CaptionButtonHeightMaximized");
auto windowedHeight = 0.0;
auto maximizedHeight = 0.0;
if (res.HasKey(windowedHeightKey))
{
const auto valFromResources = res.Lookup(windowedHeightKey);
windowedHeight = winrt::unbox_value_or<double>(valFromResources, 0.0);
}
if (res.HasKey(maximizedHeightKey))
{
const auto valFromResources = res.Lookup(maximizedHeightKey);
maximizedHeight = winrt::unbox_value_or<double>(valFromResources, 0.0);
}
return std::tuple<double, double>{ windowedHeight, maximizedHeight };
}();
static const auto windowedHeight = std::get<0>(heights);
static const auto maximizedHeight = std::get<1>(heights);
switch (visualState)
{
case WindowVisualState::WindowVisualStateMaximized:
CaptionButtonSpace().Height(maximizedHeight);
break;
case WindowVisualState::WindowVisualStateNormal:
case WindowVisualState::WindowVisualStateIconified:
default:
CaptionButtonSpace().Height(windowedHeight);
break;
}
}
// GH#9443: HoverButton, PressButton, ClickButton and ReleaseButtons are all
// used to manually interact with the buttons, in the same way that XAML
// would normally send events.
void TitlebarControl::HoverButton(CaptionButton button)
void TitlebarControl::HoverButton(CaptionButton /*button*/)
{
MinMaxCloseControl().HoverButton(button);
// MinMaxCloseControl().HoverButton(button);
}
void TitlebarControl::PressButton(CaptionButton button)
void TitlebarControl::PressButton(CaptionButton /*button*/)
{
MinMaxCloseControl().PressButton(button);
// MinMaxCloseControl().PressButton(button);
}
winrt::fire_and_forget TitlebarControl::ClickButton(CaptionButton button)
{
@@ -120,7 +162,7 @@ namespace winrt::TerminalApp::implementation
// the "Hovered" state when we minimize. This will leave the button
// visibly hovered in the taskbar preview for our window.
auto weakThis{ get_weak() };
co_await MinMaxCloseControl().Dispatcher();
co_await CaptionButtonSpace().Dispatcher();
if (auto self{ weakThis.get() })
{
// Just handle this in the same way we would if the button were
@@ -141,7 +183,7 @@ namespace winrt::TerminalApp::implementation
}
void TitlebarControl::ReleaseButtons()
{
MinMaxCloseControl().ReleaseButtons();
// MinMaxCloseControl().ReleaseButtons();
}
}

View File

@@ -13,7 +13,6 @@
VerticalAlignment="Top"
d:DesignHeight="36"
d:DesignWidth="400"
Background="{ThemeResource TabViewBackground}"
SizeChanged="Root_SizeChanged"
mc:Ignorable="d">
@@ -26,6 +25,26 @@
accent color. (which is GH#1963)
-->
<Grid.Resources>
<ResourceDictionary>
<!--
"CaptionButtonHeightWindowed" and
"CaptionButtonHeightMaximized" define the size we should use
for the caption buttons height for the windowed and maximized
states, respectively.
32 was chosen for the Maximized height to match the height of
the TabRowControl. This way, when the window is maximized, the
tabs will be flush with the top of the window. See GH#2541 for
details.
-->
<x:Double x:Key="CaptionButtonHeightWindowed">40.0</x:Double>
<!-- 32 + 1 to compensate for GH#10746 -->
<x:Double x:Key="CaptionButtonHeightMaximized">33.0</x:Double>
</ResourceDictionary>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
@@ -40,9 +59,15 @@
MinWidth="45.0"
DoubleTapped="DragBar_DoubleTapped" />
<local:MinMaxCloseControl x:Name="MinMaxCloseControl"
<!-- <local:MinMaxCloseControl x:Name="MinMaxCloseControl"
Grid.Column="2"
HorizontalAlignment="Right" />
HorizontalAlignment="Right" />-->
<Border x:Name="CaptionButtonSpace"
Grid.Column="2"
Height="{StaticResource CaptionButtonHeightWindowed}"
MinWidth="138.0"
Background="Transparent" />
<!-- This border needs to be added manually until GH#10320 is fixed -->
<Border Grid.Column="1"

View File

@@ -503,6 +503,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
RootGrid().Background(solidColor);
}
BackgroundBrush(RootGrid().Background());
}
// Method Description:

View File

@@ -117,6 +117,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void AdjustOpacity(const double opacity, const bool relative);
WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);
// -------------------------------- WinRT Events ---------------------------------
// clang-format off
WINRT_CALLBACK(FontSizeChanged, Control::FontSizeChangedEventArgs);
@@ -140,6 +142,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
TYPED_EVENT(WarningBell, IInspectable, IInspectable);
// clang-format on
WINRT_OBSERVABLE_PROPERTY(winrt::Windows::UI::Xaml::Media::Brush, BackgroundBrush, _PropertyChangedHandlers, nullptr);
private:
friend struct TermControlT<TermControl>; // friend our parent so it can bind private event handlers

View File

@@ -14,7 +14,8 @@ namespace Microsoft.Terminal.Control
[default_interface] runtimeclass TermControl : Windows.UI.Xaml.Controls.UserControl,
IDirectKeyListener,
IMouseWheelListener,
ICoreState
ICoreState,
Windows.UI.Xaml.Data.INotifyPropertyChanged
{
TermControl(IControlSettings settings,
IControlAppearance unfocusedAppearance,
@@ -85,5 +86,6 @@ namespace Microsoft.Terminal.Control
// opacity set by the settings should call this instead.
Double BackgroundOpacity { get; };
Windows.UI.Xaml.Media.Brush BackgroundBrush { get; };
}
}

View File

@@ -41,17 +41,18 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
L"zh-Hant-TW",
};
GlobalAppearance::GlobalAppearance()
GlobalAppearance::GlobalAppearance() :
_ThemeList{ single_threaded_observable_vector<Model::Theme>() }
{
InitializeComponent();
INITIALIZE_BINDABLE_ENUM_SETTING(Theme, ElementTheme, winrt::Windows::UI::Xaml::ElementTheme, L"Globals_Theme", L"Content");
INITIALIZE_BINDABLE_ENUM_SETTING(TabWidthMode, TabViewWidthMode, winrt::Microsoft::UI::Xaml::Controls::TabViewWidthMode, L"Globals_TabWidthMode", L"Content");
}
void GlobalAppearance::OnNavigatedTo(const NavigationEventArgs& e)
{
_State = e.Parameter().as<Editor::GlobalAppearancePageNavigationState>();
_UpdateThemeList();
}
winrt::hstring GlobalAppearance::LanguageDisplayConverter(const winrt::hstring& tag)
@@ -195,4 +196,66 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
}
}
// Function Description:
// - Updates the list of all themes available to choose from.
void GlobalAppearance::_UpdateThemeList()
{
// Surprisingly, though this is called every time we navigate to the page,
// the list does not keep growing on each navigation.
const auto& ThemeMap{ _State.Globals().Themes() };
for (const auto& pair : ThemeMap)
{
const auto& theme{ pair.Value() };
const auto& name{ theme.Name() };
theme;
name;
_ThemeList.Append(theme);
}
}
winrt::Windows::Foundation::IInspectable GlobalAppearance::CurrentTheme()
{
return _State.Globals().CurrentTheme();
}
// Get the name out of the newly selected item, stash that as the Theme name
// set for the globals. That controls which theme is actually the current
// theme.
void GlobalAppearance::CurrentTheme(const winrt::Windows::Foundation::IInspectable& tag)
{
if (const auto& theme{ tag.try_as<Model::Theme>() })
{
_State.Globals().Theme(theme.Name());
}
}
// Method Description:
// - Convert the names of the inbox themes to some more descriptive,
// well-known values. If the passed in theme isn't an inbox one, then just
// return its set Name.
// - "light" becomes "Light"
// - "dark" becomes "Dark"
// - "system" becomes "Use Windows theme"
// - These values are all localized based on the app language.
// Arguments:
// - theme: the theme to get the display name for.
// Return Value:
// - the potentially localized name to use for this Theme.
winrt::hstring GlobalAppearance::WellKnownThemeNameConverter(const Model::Theme& theme)
{
if (theme.Name() == L"dark")
{
return RS_(L"Globals_ThemeDark/Content");
}
if (theme.Name() == L"light")
{
return RS_(L"Globals_ThemeLight/Content");
}
if (theme.Name() == L"system")
{
return RS_(L"Globals_ThemeSystem/Content");
}
return theme.Name();
}
}

View File

@@ -26,9 +26,10 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
void OnNavigatedTo(const winrt::Windows::UI::Xaml::Navigation::NavigationEventArgs& e);
WINRT_PROPERTY(Editor::GlobalAppearancePageNavigationState, State, nullptr);
GETSET_BINDABLE_ENUM_SETTING(Theme, winrt::Windows::UI::Xaml::ElementTheme, State().Globals().Theme);
GETSET_BINDABLE_ENUM_SETTING(TabWidthMode, winrt::Microsoft::UI::Xaml::Controls::TabViewWidthMode, State().Globals().TabWidthMode);
WINRT_PROPERTY(Windows::Foundation::Collections::IObservableVector<Model::Theme>, ThemeList, nullptr);
public:
// LanguageDisplayConverter maps the given BCP 47 tag to a localized string.
// For instance "en-US" produces "English (United States)", while "de-DE" produces
@@ -40,9 +41,16 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
winrt::Windows::Foundation::IInspectable CurrentLanguage();
void CurrentLanguage(const winrt::Windows::Foundation::IInspectable& tag);
winrt::Windows::Foundation::IInspectable CurrentTheme();
void CurrentTheme(const winrt::Windows::Foundation::IInspectable& tag);
static winrt::hstring WellKnownThemeNameConverter(const Model::Theme& theme);
private:
winrt::Windows::Foundation::Collections::IObservableVector<winrt::hstring> _languageList;
winrt::Windows::Foundation::IInspectable _currentLanguage;
winrt::Windows::Foundation::IInspectable _currentTheme;
void _UpdateThemeList();
};
}

View File

@@ -21,7 +21,8 @@ namespace Microsoft.Terminal.Settings.Editor
IInspectable CurrentLanguage;
IInspectable CurrentTheme;
Windows.Foundation.Collections.IObservableVector<Microsoft.Terminal.Settings.Editor.EnumEntry> ThemeList { get; };
static String WellKnownThemeNameConverter(Microsoft.Terminal.Settings.Model.Theme theme);
Windows.Foundation.Collections.IObservableVector<Microsoft.Terminal.Settings.Model.Theme> ThemeList { get; };
IInspectable CurrentTabWidthMode;
Windows.Foundation.Collections.IObservableVector<Microsoft.Terminal.Settings.Editor.EnumEntry> TabWidthModeList { get; };

View File

@@ -8,6 +8,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Microsoft.Terminal.Settings.Editor"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:model="using:Microsoft.Terminal.Settings.Model"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
mc:Ignorable="d">
@@ -42,10 +43,15 @@
<!-- Theme -->
<local:SettingContainer x:Uid="Globals_Theme">
<ComboBox AutomationProperties.AccessibilityView="Content"
ItemTemplate="{StaticResource EnumComboBoxTemplate}"
ItemsSource="{x:Bind ThemeList, Mode=OneWay}"
SelectedItem="{x:Bind CurrentTheme, Mode=TwoWay}"
Style="{StaticResource ComboBoxSettingStyle}" />
Style="{StaticResource ComboBoxSettingStyle}">
<ComboBox.ItemTemplate>
<DataTemplate x:DataType="model:Theme">
<TextBlock Text="{x:Bind local:GlobalAppearance.WellKnownThemeNameConverter((model:Theme)), Mode=OneWay}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</local:SettingContainer>
<!-- Always show tabs -->

View File

@@ -73,6 +73,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
const Json::Value& colorSchemes;
const Json::Value& profileDefaults;
const Json::Value& profilesList;
const Json::Value& themes;
};
static std::pair<size_t, size_t> _lineAndColumnFromPosition(const std::string_view& string, const size_t position);

View File

@@ -39,6 +39,7 @@ static constexpr std::string_view ProfilesKey{ "profiles" };
static constexpr std::string_view DefaultSettingsKey{ "defaults" };
static constexpr std::string_view ProfilesListKey{ "list" };
static constexpr std::string_view SchemesKey{ "schemes" };
static constexpr std::string_view ThemesKey{ "themes" };
static constexpr std::wstring_view jsonExtension{ L".json" };
static constexpr std::wstring_view FragmentsSubDirectory{ L"\\Fragments" };
@@ -529,6 +530,23 @@ void SettingsLoader::_parse(const OriginTag origin, const winrt::hstring& source
}
}
{
for (const auto& themeJson : json.themes)
{
if (const auto theme = Theme::FromJson(themeJson))
{
if (origin != OriginTag::InBox &&
(theme->Name() == L"system" || theme->Name() == L"light" || theme->Name() == L"dark"))
{
// If the theme didn't come from the in box themes, and it's
// name was one of the reserved names, then just ignore it.
continue;
}
settings.globals->AddTheme(*theme);
}
}
}
{
settings.baseLayerProfile = Profile::FromJson(json.profileDefaults);
// Remove the `guid` member from the default settings.
@@ -627,10 +645,11 @@ SettingsLoader::JsonSettings SettingsLoader::_parseJson(const std::string_view&
{
auto root = content.empty() ? Json::Value{ Json::ValueType::objectValue } : _parseJSON(content);
const auto& colorSchemes = _getJSONValue(root, SchemesKey);
const auto& themes = _getJSONValue(root, ThemesKey);
const auto& profilesObject = _getJSONValue(root, ProfilesKey);
const auto& profileDefaults = _getJSONValue(profilesObject, DefaultSettingsKey);
const auto& profilesList = profilesObject.isArray() ? profilesObject : _getJSONValue(profilesObject, ProfilesListKey);
return JsonSettings{ std::move(root), colorSchemes, profileDefaults, profilesList };
return JsonSettings{ std::move(root), colorSchemes, profileDefaults, profilesList, themes };
}
// Just a common helper function between _parse and _parseFragment.
@@ -1055,6 +1074,20 @@ Json::Value CascadiaSettings::ToJson() const
}
json[JsonKey(SchemesKey)] = schemes;
Json::Value themes{ Json::ValueType::arrayValue };
for (const auto& entry : _globals->Themes())
{
// Ignore the built in themes, when serializing the themes back out. We
// don't want to re-include them in the user settings file.
const auto theme{ winrt::get_self<Theme>(entry.Value()) };
if (theme->Name() == L"system" || theme->Name() == L"light" || theme->Name() == L"dark")
{
continue;
}
themes.append(theme->ToJson());
}
json[JsonKey(ThemesKey)] = themes;
return json;
}

View File

@@ -17,6 +17,7 @@ using namespace winrt::Microsoft::UI::Xaml::Controls;
static constexpr std::string_view LegacyKeybindingsKey{ "keybindings" };
static constexpr std::string_view ActionsKey{ "actions" };
static constexpr std::string_view ThemeKey{ "theme" };
static constexpr std::string_view DefaultProfileKey{ "defaultProfile" };
static constexpr std::string_view LegacyUseTabSwitcherModeKey{ "useTabSwitcher" };
@@ -39,6 +40,14 @@ void GlobalAppSettings::_FinalizeInheritance()
_colorSchemes.Insert(k, v);
}
}
for (const auto& [k, v] : parent->_themes)
{
if (!_themes.HasKey(k))
{
_themes.Insert(k, v);
}
}
}
}
@@ -65,6 +74,14 @@ winrt::com_ptr<GlobalAppSettings> GlobalAppSettings::Copy() const
globals->_colorSchemes.Insert(kv.Key(), *schemeImpl->Copy());
}
}
if (_themes)
{
for (auto kv : _themes)
{
const auto themeImpl{ winrt::get_self<implementation::Theme>(kv.Value()) };
globals->_themes.Insert(kv.Key(), *themeImpl->Copy());
}
}
for (const auto& parent : _parents)
{
@@ -192,3 +209,17 @@ Json::Value GlobalAppSettings::ToJson() const
json[JsonKey(ActionsKey)] = _actionMap->ToJson();
return json;
}
winrt::Microsoft::Terminal::Settings::Model::Theme GlobalAppSettings::CurrentTheme() noexcept
{
return _themes.HasKey(Theme()) ? _themes.Lookup(Theme()) : nullptr;
}
void GlobalAppSettings::AddTheme(const Model::Theme& theme)
{
_themes.Insert(theme.Name(), theme);
}
winrt::Windows::Foundation::Collections::IMapView<winrt::hstring, winrt::Microsoft::Terminal::Settings::Model::Theme> GlobalAppSettings::Themes() noexcept
{
return _themes.GetView();
}

View File

@@ -22,6 +22,7 @@ Author(s):
#include "ActionMap.h"
#include "Command.h"
#include "ColorScheme.h"
#include "Theme.h"
// fwdecl unittest classes
namespace SettingsModelLocalTests
@@ -62,6 +63,10 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
DisableAnimations(!invertedDisableAnimationsValue);
}
Windows::Foundation::Collections::IMapView<hstring, Model::Theme> Themes() noexcept;
void AddTheme(const Model::Theme& theme);
Model::Theme CurrentTheme() noexcept;
INHERITABLE_SETTING(Model::GlobalAppSettings, hstring, UnparsedDefaultProfile, L"");
#define GLOBAL_SETTINGS_INITIALIZE(type, name, jsonKey, ...) \
@@ -78,7 +83,9 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
winrt::guid _defaultProfile;
winrt::com_ptr<implementation::ActionMap> _actionMap{ winrt::make_self<implementation::ActionMap>() };
std::vector<SettingsLoadWarnings> _keybindingsWarnings;
Windows::Foundation::Collections::IMap<winrt::hstring, Model::ColorScheme> _colorSchemes{ winrt::single_threaded_map<winrt::hstring, Model::ColorScheme>() };
Windows::Foundation::Collections::IMap<winrt::hstring, Model::Theme> _themes{ winrt::single_threaded_map<winrt::hstring, Model::Theme>() };
};
}

View File

@@ -3,6 +3,7 @@
#include "IInheritable.idl.h"
import "Theme.idl";
import "ColorScheme.idl";
import "ActionMap.idl";
@@ -54,7 +55,6 @@ namespace Microsoft.Terminal.Settings.Model
INHERITABLE_SETTING(Boolean, ShowTitleInTitlebar);
INHERITABLE_SETTING(Boolean, ConfirmCloseAllTabs);
INHERITABLE_SETTING(String, Language);
INHERITABLE_SETTING(Windows.UI.Xaml.ElementTheme, Theme);
INHERITABLE_SETTING(Microsoft.UI.Xaml.Controls.TabViewWidthMode, TabWidthMode);
INHERITABLE_SETTING(Boolean, UseAcrylicInTabRow);
INHERITABLE_SETTING(Boolean, ShowTabsInTitlebar);
@@ -94,5 +94,10 @@ namespace Microsoft.Terminal.Settings.Model
void RemoveColorScheme(String schemeName);
ActionMap ActionMap { get; };
Windows.Foundation.Collections.IMapView<String, Theme> Themes();
void AddTheme(Theme theme);
INHERITABLE_SETTING(String, Theme);
Theme CurrentTheme { get; };
}
}

View File

@@ -33,8 +33,8 @@ Author(s):
X(bool, AlwaysShowTabs, "alwaysShowTabs", true) \
X(bool, ShowTitleInTitlebar, "showTerminalTitleInTitlebar", true) \
X(bool, ConfirmCloseAllTabs, "confirmCloseAllTabs", true) \
X(hstring, Theme, "theme") \
X(hstring, Language, "language") \
X(winrt::Windows::UI::Xaml::ElementTheme, Theme, "theme", winrt::Windows::UI::Xaml::ElementTheme::Default) \
X(winrt::Microsoft::UI::Xaml::Controls::TabViewWidthMode, TabWidthMode, "tabWidthMode", winrt::Microsoft::UI::Xaml::Controls::TabViewWidthMode::Equal) \
X(bool, UseAcrylicInTabRow, "useAcrylicInTabRow", false) \
X(bool, ShowTabsInTitlebar, "showTabsInTitlebar", true) \
@@ -112,3 +112,14 @@ Author(s):
// Intentionally omitted Appearance settings:
// * ForegroundKey, BackgroundKey, SelectionBackgroundKey, CursorColorKey: all optional colors
// * Opacity: needs special parsing
#define MTSM_THEME_SETTINGS(X) \
X(winrt::Microsoft::Terminal::Settings::Model::WindowTheme, Window, "window", nullptr) \
X(winrt::Microsoft::Terminal::Settings::Model::TabRowTheme, TabRow, "tabRow", nullptr)
#define MTSM_THEME_WINDOW_SETTINGS(X) \
X(winrt::Windows::UI::Xaml::ElementTheme, RequestedTheme, "applicationTheme", winrt::Windows::UI::Xaml::ElementTheme::Default) \
X(bool, UseMica, "useMica", false)
#define MTSM_THEME_TABROW_SETTINGS(X) \
X(winrt::Microsoft::Terminal::Settings::Model::ThemeColor, Background, "background", nullptr)

View File

@@ -48,6 +48,9 @@
<ClInclude Include="ColorScheme.h">
<DependentUpon>ColorScheme.idl</DependentUpon>
</ClInclude>
<ClInclude Include="Theme.h">
<DependentUpon>Theme.idl</DependentUpon>
</ClInclude>
<ClInclude Include="Command.h">
<DependentUpon>Command.idl</DependentUpon>
</ClInclude>
@@ -128,6 +131,9 @@
<ClCompile Include="ColorScheme.cpp">
<DependentUpon>ColorScheme.idl</DependentUpon>
</ClCompile>
<ClCompile Include="Theme.cpp">
<DependentUpon>Theme.idl</DependentUpon>
</ClCompile>
<ClCompile Include="Command.cpp">
<DependentUpon>Command.idl</DependentUpon>
</ClCompile>
@@ -173,6 +179,7 @@
<Midl Include="ApplicationState.idl" />
<Midl Include="CascadiaSettings.idl" />
<Midl Include="ColorScheme.idl" />
<Midl Include="Theme.idl" />
<Midl Include="Command.idl" />
<Midl Include="DefaultTerminal.idl" />
<Midl Include="GlobalAppSettings.idl" />

View File

@@ -546,3 +546,63 @@ JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Settings::Model::InfoBarMessage)
pair_type{ "setAsDefault", ValueType::SetAsDefault },
};
};
template<>
struct ::Microsoft::Terminal::Settings::Model::JsonUtils::ConversionTrait<winrt::Microsoft::Terminal::Settings::Model::ThemeColor>
{
winrt::Microsoft::Terminal::Settings::Model::ThemeColor FromJson(const Json::Value& json)
{
const auto string{ Detail::GetStringView(json) };
if (string == "accent")
{
return winrt::Microsoft::Terminal::Settings::Model::ThemeColor::FromAccent();
}
else if (string == "terminalBackground")
{
return winrt::Microsoft::Terminal::Settings::Model::ThemeColor::FromTerminalBackground();
}
else
{
return winrt::Microsoft::Terminal::Settings::Model::ThemeColor::FromColor(::Microsoft::Console::Utils::ColorFromHexString(string));
}
}
bool CanConvert(const Json::Value& json)
{
if (!json.isString())
{
return false;
}
const auto string{ Detail::GetStringView(json) };
const auto isColorSpec = (string.length() == 9 || string.length() == 7 || string.length() == 4) && string.front() == '#';
const auto isAccent = string == "accent";
const auto isTerminalBackground = string == "terminalBackground";
return isColorSpec || isAccent || isTerminalBackground;
}
Json::Value ToJson(const winrt::Microsoft::Terminal::Settings::Model::ThemeColor& val)
{
switch (val.ColorType())
{
case winrt::Microsoft::Terminal::Settings::Model::ThemeColorType::Accent:
{
return "accent";
}
case winrt::Microsoft::Terminal::Settings::Model::ThemeColorType::Color:
{
return til::u16u8(til::color{ val.Color() }.ToHexString(false));
}
case winrt::Microsoft::Terminal::Settings::Model::ThemeColorType::TerminalBackground:
{
return "terminalBackground";
}
}
return til::u16u8(til::color{ val.Color() }.ToHexString(false));
}
std::string TypeDescription() const
{
return "ThemeColor (#rrggbb, #rgb, #aarrggbb, accent, terminalBackground)";
}
};

View File

@@ -0,0 +1,263 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "Theme.h"
#include "../../types/inc/Utils.hpp"
#include "../../types/inc/colorTable.hpp"
#include "Utils.h"
#include "JsonUtils.h"
#include "TerminalSettingsSerializationHelpers.h"
#include "ThemeColor.g.cpp"
#include "WindowTheme.g.cpp"
#include "TabRowTheme.g.cpp"
#include "Theme.g.cpp"
using namespace ::Microsoft::Console;
using namespace Microsoft::Terminal::Settings::Model;
using namespace winrt::Microsoft::Terminal::Settings::Model::implementation;
using namespace winrt::Windows::UI;
static constexpr std::string_view NameKey{ "name" };
static constexpr wchar_t RegKeyDwm[] = L"Software\\Microsoft\\Windows\\DWM";
static constexpr wchar_t RegKeyAccentColor[] = L"AccentColor";
winrt::Microsoft::Terminal::Settings::Model::ThemeColor ThemeColor::FromColor(const winrt::Microsoft::Terminal::Core::Color& coreColor) noexcept
{
auto result = winrt::make_self<implementation::ThemeColor>();
result->_Color = coreColor;
result->_ColorType = ThemeColorType::Color;
return *result;
}
winrt::Microsoft::Terminal::Settings::Model::ThemeColor ThemeColor::FromAccent() noexcept
{
auto result = winrt::make_self<implementation::ThemeColor>();
result->_ColorType = ThemeColorType::Accent;
return *result;
}
winrt::Microsoft::Terminal::Settings::Model::ThemeColor ThemeColor::FromTerminalBackground() noexcept
{
auto result = winrt::make_self<implementation::ThemeColor>();
result->_ColorType = ThemeColorType::TerminalBackground;
return *result;
}
static wil::unique_hkey openDwmRegKey()
{
HKEY hKey{ nullptr };
if (RegOpenKeyEx(HKEY_CURRENT_USER, RegKeyDwm, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
{
return wil::unique_hkey{ hKey };
}
return nullptr;
}
static DWORD readDwmSubValue(const wil::unique_hkey& dwmRootKey, const wchar_t* key)
{
DWORD val{ 0 };
DWORD size{ sizeof(val) };
LOG_IF_FAILED(RegQueryValueExW(dwmRootKey.get(), key, nullptr, nullptr, reinterpret_cast<BYTE*>(&val), &size));
return val;
}
static til::color _getAccentColorForTitlebar()
{
return til::color{ static_cast<COLORREF>(readDwmSubValue(openDwmRegKey(), RegKeyAccentColor)) };
}
til::color ThemeColor::ColorFromBrush(const winrt::Windows::UI::Xaml::Media::Brush& brush)
{
if (auto acrylic = brush.try_as<winrt::Windows::UI::Xaml::Media::AcrylicBrush>())
{
return acrylic.TintColor();
}
else if (auto solidColor = brush.try_as<winrt::Windows::UI::Xaml::Media::SolidColorBrush>())
{
return solidColor.Color();
}
return {};
}
winrt::Windows::UI::Xaml::Media::Brush ThemeColor::Evaluate(const winrt::Windows::UI::Xaml::ResourceDictionary& res,
const winrt::Windows::UI::Xaml::Media::Brush& terminalBackground,
const bool forTitlebar)
{
static const auto accentColorKey{ winrt::box_value(L"SystemAccentColor") };
switch (ColorType())
{
case ThemeColorType::Accent:
{
til::color accentColor;
if (forTitlebar)
{
accentColor = _getAccentColorForTitlebar();
}
else
{
accentColor = winrt::unbox_value<winrt::Windows::UI::Color>(res.Lookup(accentColorKey));
}
const auto accentBrush = winrt::Windows::UI::Xaml::Media::SolidColorBrush();
accentBrush.Color(accentColor);
return accentBrush;
}
case ThemeColorType::Color:
{
const auto solidBrush = winrt::Windows::UI::Xaml::Media::SolidColorBrush();
solidBrush.Color(Color());
return solidBrush;
}
case ThemeColorType::TerminalBackground:
{
return terminalBackground;
}
}
return nullptr;
}
#define THEME_SETTINGS_FROM_JSON(type, name, jsonKey, ...) \
result->name(JsonUtils::GetValueForKey<type>(json, jsonKey));
#define THEME_SETTINGS_TO_JSON(type, name, jsonKey, ...) \
JsonUtils::SetValueForKey(json, jsonKey, val.name());
#define THEME_OBJECT_CONVERTER(nameSpace, name, macro) \
template<> \
struct ::Microsoft::Terminal::Settings::Model::JsonUtils::ConversionTrait<nameSpace::name> \
{ \
nameSpace::name FromJson(const Json::Value& json) \
{ \
auto result = winrt::make_self<nameSpace::implementation::name>(); \
macro(THEME_SETTINGS_FROM_JSON); \
return *result; \
} \
\
bool CanConvert(const Json::Value& json) \
{ \
return json.isObject(); \
} \
\
Json::Value ToJson(const nameSpace::name& val) \
{ \
if (val == nullptr) \
return Json::Value::null; \
Json::Value json{ Json::ValueType::objectValue }; \
macro(THEME_SETTINGS_TO_JSON); \
return json; \
} \
\
std::string TypeDescription() const \
{ \
return "name (You should never see this)"; \
} \
};
THEME_OBJECT_CONVERTER(winrt::Microsoft::Terminal::Settings::Model, WindowTheme, MTSM_THEME_WINDOW_SETTINGS);
THEME_OBJECT_CONVERTER(winrt::Microsoft::Terminal::Settings::Model, TabRowTheme, MTSM_THEME_TABROW_SETTINGS);
#undef THEME_SETTINGS_FROM_JSON
#undef THEME_SETTINGS_TO_JSON
#undef THEME_OBJECT_CONVERTER
Theme::Theme() noexcept :
Theme{ winrt::Windows::UI::Xaml::ElementTheme::Default }
{
}
Theme::Theme(const winrt::Windows::UI::Xaml::ElementTheme& requestedTheme) noexcept
{
auto window{ winrt::make_self<implementation::WindowTheme>() };
window->RequestedTheme(requestedTheme);
_Window = *window;
}
winrt::com_ptr<Theme> Theme::Copy() const
{
auto theme{ winrt::make_self<Theme>() };
theme->_Name = _Name;
if (_Window)
{
theme->_Window = *winrt::get_self<implementation::WindowTheme>(_Window)->Copy();
}
if (_TabRow)
{
theme->_TabRow = *winrt::get_self<implementation::TabRowTheme>(_TabRow)->Copy();
}
return theme;
}
// Method Description:
// - Create a new instance of this class from a serialized JsonObject.
// Arguments:
// - json: an object which should be a serialization of a ColorScheme object.
// Return Value:
// - Returns nullptr for invalid JSON.
winrt::com_ptr<Theme> Theme::FromJson(const Json::Value& json)
{
auto result = winrt::make_self<Theme>();
result->LayerJson(json);
return result;
}
void Theme::LayerJson(const Json::Value& json)
{
if (json.isString())
{
// We found a string, not an object. Just secretly promote that string
// to a theme object with just the applicationTheme set from that value.
JsonUtils::GetValue(json, _Name);
winrt::Windows::UI::Xaml::ElementTheme requestedTheme{ winrt::Windows::UI::Xaml::ElementTheme::Default };
JsonUtils::GetValue(json, requestedTheme);
auto window{ winrt::make_self<implementation::WindowTheme>() };
window->RequestedTheme(requestedTheme);
_Window = *window;
return;
}
JsonUtils::GetValueForKey(json, NameKey, _Name);
// This will use each of the ConversionTrait's from above to quickly parse the sub-objects
#define THEME_SETTINGS_LAYER_JSON(type, name, jsonKey, ...) \
JsonUtils::GetValueForKey(json, jsonKey, _##name);
MTSM_THEME_SETTINGS(THEME_SETTINGS_LAYER_JSON)
#undef THEME_SETTINGS_LAYER_JSON
}
// Method Description:
// - Create a new serialized JsonObject from an instance of this class
// Arguments:
// - <none>
// Return Value:
// - the JsonObject representing this instance
Json::Value Theme::ToJson() const
{
Json::Value json{ Json::ValueType::objectValue };
JsonUtils::SetValueForKey(json, NameKey, _Name);
// Don't serialize anything if the object is null.
#define THEME_SETTINGS_TO_JSON(type, name, jsonKey, ...) \
if (_##name) \
JsonUtils::SetValueForKey(json, jsonKey, _##name);
MTSM_THEME_SETTINGS(THEME_SETTINGS_TO_JSON)
#undef THEME_SETTINGS_TO_JSON
return json;
}
winrt::hstring Theme::ToString()
{
return Name();
}

View File

@@ -0,0 +1,108 @@
/*++
Copyright (c) Microsoft Corporation
Licensed under the MIT license.
Module Name:
- Theme.hpp
Abstract:
- A Theme represents a collection of settings which control the appearance of
the Terminal window itself. Things like the color of the titlebar, the style
of the tabs.
Author(s):
- Mike Griese - March 2022
--*/
#pragma once
#include "../../inc/conattrs.hpp"
#include "DefaultSettings.h"
#include "IInheritable.h"
#include "MTSMSettings.h"
#include "ThemeColor.g.h"
#include "WindowTheme.g.h"
#include "TabRowTheme.g.h"
#include "Theme.g.h"
namespace winrt::Microsoft::Terminal::Settings::Model::implementation
{
struct ThemeColor : ThemeColorT<ThemeColor>
{
public:
ThemeColor() noexcept = default;
static winrt::Microsoft::Terminal::Settings::Model::ThemeColor FromColor(const winrt::Microsoft::Terminal::Core::Color& coreColor) noexcept;
static winrt::Microsoft::Terminal::Settings::Model::ThemeColor FromAccent() noexcept;
static winrt::Microsoft::Terminal::Settings::Model::ThemeColor FromTerminalBackground() noexcept;
static til::color ColorFromBrush(const winrt::Windows::UI::Xaml::Media::Brush& brush);
winrt::Windows::UI::Xaml::Media::Brush Evaluate(const winrt::Windows::UI::Xaml::ResourceDictionary& res,
const winrt::Windows::UI::Xaml::Media::Brush& terminalBackground,
const bool forTitlebar);
WINRT_PROPERTY(til::color, Color);
WINRT_PROPERTY(winrt::Microsoft::Terminal::Settings::Model::ThemeColorType, ColorType);
};
#define THEME_SETTINGS_INITIALIZE(type, name, jsonKey, ...) \
WINRT_PROPERTY(type, name, ##__VA_ARGS__)
#define THEME_SETTINGS_COPY(type, name, jsonKey, ...) \
result->_##name = _##name;
#define COPY_THEME_OBJECT(T, macro) \
winrt::com_ptr<T> Copy() \
{ \
auto result{ winrt::make_self<T>() }; \
macro(THEME_SETTINGS_COPY); \
return result; \
}
struct WindowTheme : WindowThemeT<WindowTheme>
{
MTSM_THEME_WINDOW_SETTINGS(THEME_SETTINGS_INITIALIZE);
public:
COPY_THEME_OBJECT(WindowTheme, MTSM_THEME_WINDOW_SETTINGS);
};
struct TabRowTheme : TabRowThemeT<TabRowTheme>
{
MTSM_THEME_TABROW_SETTINGS(THEME_SETTINGS_INITIALIZE);
public:
COPY_THEME_OBJECT(TabRowTheme, MTSM_THEME_TABROW_SETTINGS);
};
struct Theme : ThemeT<Theme>
{
public:
Theme() noexcept;
Theme(const winrt::Windows::UI::Xaml::ElementTheme& requestedTheme) noexcept;
com_ptr<Theme> Copy() const;
hstring ToString();
static com_ptr<Theme> FromJson(const Json::Value& json);
void LayerJson(const Json::Value& json);
Json::Value ToJson() const;
WINRT_PROPERTY(winrt::hstring, Name);
MTSM_THEME_SETTINGS(THEME_SETTINGS_INITIALIZE)
private:
};
#undef THEME_SETTINGS_INITIALIZE
#undef THEME_SETTINGS_COPY
}
namespace winrt::Microsoft::Terminal::Settings::Model::factory_implementation
{
BASIC_FACTORY(ThemeColor);
BASIC_FACTORY(Theme);
}

View File

@@ -0,0 +1,52 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
namespace Microsoft.Terminal.Settings.Model
{
enum ThemeColorType
{
Accent,
Color,
TerminalBackground
};
runtimeclass ThemeColor
{
ThemeColor();
static ThemeColor FromColor(Microsoft.Terminal.Core.Color color);
static ThemeColor FromAccent();
static ThemeColor FromTerminalBackground();
Microsoft.Terminal.Core.Color Color { get; };
ThemeColorType ColorType;
static Microsoft.Terminal.Core.Color ColorFromBrush(Windows.UI.Xaml.Media.Brush brush);
Windows.UI.Xaml.Media.Brush Evaluate(Windows.UI.Xaml.ResourceDictionary res,
Windows.UI.Xaml.Media.Brush terminalBackground,
Boolean forTitlebar);
}
runtimeclass WindowTheme {
Windows.UI.Xaml.ElementTheme RequestedTheme { get; };
Boolean UseMica { get; };
}
runtimeclass TabRowTheme {
ThemeColor Background { get; };
}
[default_interface] runtimeclass Theme : Windows.Foundation.IStringable {
Theme();
Theme(Windows.UI.Xaml.ElementTheme requestedTheme);
String Name;
// window.* Namespace
WindowTheme Window { get; };
// tabRow.* Namespace
TabRowTheme TabRow { get; };
}
}

View File

@@ -280,6 +280,26 @@
"brightWhite": "#EEEEEC"
}
],
"themes": [
{
"name": "light",
"window":{
"applicationTheme": "light"
}
},
{
"name": "dark",
"window":{
"applicationTheme": "dark"
}
},
{
"name": "system",
"window":{
"applicationTheme": "system"
}
}
],
"actions":
[
// Application-level Keys

View File

@@ -390,6 +390,11 @@ void AppHost::Initialize()
}
});
// Load bearing: make sure the PropertyChanged handler is added before we
// call Create, so that when the app sets up the titlebar brush, we're
// already prepared to listen for the change notification
_revokers.PropertyChanged = _logic.PropertyChanged(winrt::auto_revoke, { this, &AppHost::_PropertyChangedHandler });
_logic.Create();
_revokers.TitleChanged = _logic.TitleChanged(winrt::auto_revoke, { this, &AppHost::AppTitleChanged });
@@ -683,8 +688,12 @@ void AppHost::_UpdateTitleBarContent(const winrt::Windows::Foundation::IInspecta
{
if (_useNonClientArea)
{
(static_cast<NonClientIslandWindow*>(_window.get()))->SetTitlebarContent(arg);
auto nonClientWindow{ static_cast<NonClientIslandWindow*>(_window.get()) };
nonClientWindow->SetTitlebarContent(arg);
nonClientWindow->SetTitlebarBackground(_logic.TitlebarBrush());
}
_updateTheme();
}
// Method Description:
@@ -695,9 +704,9 @@ void AppHost::_UpdateTitleBarContent(const winrt::Windows::Foundation::IInspecta
// - arg: the ElementTheme to use as the new theme for the UI
// Return Value:
// - <none>
void AppHost::_UpdateTheme(const winrt::Windows::Foundation::IInspectable&, const winrt::Windows::UI::Xaml::ElementTheme& arg)
void AppHost::_UpdateTheme(const winrt::Windows::Foundation::IInspectable&, const winrt::Windows::UI::Xaml::ElementTheme& /*arg*/)
{
_window->OnApplicationThemeChanged(arg);
_updateTheme();
}
void AppHost::_FocusModeChanged(const winrt::Windows::Foundation::IInspectable&,
@@ -887,8 +896,15 @@ void AppHost::_FindTargetWindow(const winrt::Windows::Foundation::IInspectable&
args.ResultTargetWindowName(targetWindow.WindowName());
}
winrt::fire_and_forget AppHost::_WindowActivated()
winrt::fire_and_forget AppHost::_WindowActivated(bool activated)
{
_logic.WindowActivated(activated);
if (!activated)
{
co_return;
}
co_await winrt::resume_background();
if (auto peasant{ _windowManager.CurrentWindow() })
@@ -1311,6 +1327,19 @@ winrt::fire_and_forget AppHost::_RenameWindowRequested(const winrt::Windows::Fou
}
}
void AppHost::_updateTheme()
{
auto theme = _logic.Theme();
_window->OnApplicationThemeChanged(theme.Window().RequestedTheme());
int attribute = theme.Window().UseMica() ? /* DWMSBT_MAINWINDOW */ 2 : /*DWMSBT_NONE*/ 1;
DwmSetWindowAttribute(_window->GetHandle(), /* DWMWA_SYSTEMBACKDROP_TYPE */ 38, &attribute, sizeof(attribute));
// COLORREF none = DWMWA_COLOR_NONE;
// DwmSetWindowAttribute(_window->GetHandle(), DWMWA_CAPTION_COLOR, &none, sizeof(none));
}
void AppHost::_HandleSettingsChanged(const winrt::Windows::Foundation::IInspectable& /*sender*/,
const winrt::Windows::Foundation::IInspectable& /*args*/)
{
@@ -1342,6 +1371,7 @@ void AppHost::_HandleSettingsChanged(const winrt::Windows::Foundation::IInspecta
}
_window->SetMinimizeToNotificationAreaBehavior(_logic.GetMinimizeToNotificationArea());
_updateTheme();
}
void AppHost::_IsQuakeWindowChanged(const winrt::Windows::Foundation::IInspectable&,
@@ -1556,3 +1586,13 @@ void AppHost::_CloseRequested(const winrt::Windows::Foundation::IInspectable& /*
const auto pos = _GetWindowLaunchPosition();
_logic.CloseWindow(pos);
}
void AppHost::_PropertyChangedHandler(const winrt::Windows::Foundation::IInspectable& /*sender*/,
const winrt::Windows::UI::Xaml::Data::PropertyChangedEventArgs& e)
{
if (e.PropertyName() == L"TitlebarBrush")
{
auto nonClientWindow{ static_cast<NonClientIslandWindow*>(_window.get()) };
nonClientWindow->SetTitlebarBackground(_logic.TitlebarBrush());
}
}

View File

@@ -55,7 +55,7 @@ private:
void _RaiseVisualBell(const winrt::Windows::Foundation::IInspectable& sender,
const winrt::Windows::Foundation::IInspectable& arg);
void _WindowMouseWheeled(const til::point coord, const int32_t delta);
winrt::fire_and_forget _WindowActivated();
winrt::fire_and_forget _WindowActivated(bool activated);
void _WindowMoved();
void _DispatchCommandline(winrt::Windows::Foundation::IInspectable sender,
@@ -121,6 +121,12 @@ private:
const winrt::Windows::Foundation::IInspectable& args);
void _HideNotificationIconRequested(const winrt::Windows::Foundation::IInspectable& sender,
const winrt::Windows::Foundation::IInspectable& args);
void _updateTheme();
void _PropertyChangedHandler(const winrt::Windows::Foundation::IInspectable& sender,
const winrt::Windows::UI::Xaml::Data::PropertyChangedEventArgs& args);
std::unique_ptr<NotificationIcon> _notificationIcon;
winrt::event_token _ReAddNotificationIconToken;
winrt::event_token _NotificationIconPressedToken;
@@ -164,5 +170,6 @@ private:
winrt::Microsoft::Terminal::Remoting::WindowManager::ShowNotificationIconRequested_revoker ShowNotificationIconRequested;
winrt::Microsoft::Terminal::Remoting::WindowManager::HideNotificationIconRequested_revoker HideNotificationIconRequested;
winrt::Microsoft::Terminal::Remoting::WindowManager::QuitAllRequested_revoker QuitAllRequested;
winrt::TerminalApp::AppLogic::PropertyChanged_revoker PropertyChanged;
} _revokers{};
};

View File

@@ -439,10 +439,8 @@ long IslandWindow::_calculateTotalSize(const bool isWidth, const long clientSize
case WM_ACTIVATE:
{
// wparam = 0 indicates the window was deactivated
if (LOWORD(wparam) != 0)
{
_WindowActivatedHandlers();
}
const bool activated = LOWORD(wparam) != 0;
_WindowActivatedHandlers(activated);
break;
}

View File

@@ -67,7 +67,7 @@ public:
WINRT_CALLBACK(DragRegionClicked, winrt::delegate<>);
WINRT_CALLBACK(WindowCloseButtonClicked, winrt::delegate<>);
WINRT_CALLBACK(MouseScrolled, winrt::delegate<void(til::point, int32_t)>);
WINRT_CALLBACK(WindowActivated, winrt::delegate<void()>);
WINRT_CALLBACK(WindowActivated, winrt::delegate<void(bool)>);
WINRT_CALLBACK(HotkeyPressed, winrt::delegate<void(long)>);
WINRT_CALLBACK(NotifyNotificationIconPressed, winrt::delegate<void()>);
WINRT_CALLBACK(NotifyWindowHidden, winrt::delegate<void()>);

View File

@@ -129,6 +129,18 @@ LRESULT NonClientIslandWindow::_dragBarNcHitTest(const til::point pointer)
}
}
// We make the frame as tall as the XAML titlebar.
// We get rid of the XAML caption buttons. Replace them with a transparent hole in XAML that's exactly the size of the DWM caption btns.
// We don't extend the drag rect there, cause we don't need to anymore.
// When we set the tabRow bg, it can't be transparent, unless mica is enabled.
// - If the terminal has opacity, sorry, it's opaque now.
// - If we want arylic titlebar, then that's ookay, make sure it's hostBackdrop
// - that won't apply to the DWM caption buttons tho
// - if we get a non host-backdrop arylic terminalBG, MAKE IT HOSTBACKDROP
// We'd have to set the DWM caption color to match the one from the theme cause the buttons would still be drawn by DWM on that color, not us
// we'd lose our fukin rounded maximize button, cause ofc the DWM ones don't have that
//
// Function Description:
// - The window procedure for the drag bar forwards clicks on its client area to
// its parent as non-client clicks.
@@ -146,7 +158,7 @@ LRESULT NonClientIslandWindow::_dragBarNcHitTest(const til::point pointer)
// input via XAML.
LRESULT NonClientIslandWindow::_InputSinkMessageHandler(UINT const message,
WPARAM const wparam,
LPARAM const lparam) noexcept
LPARAM lparam) noexcept
{
switch (message)
{
@@ -154,7 +166,17 @@ LRESULT NonClientIslandWindow::_InputSinkMessageHandler(UINT const message,
{
// Try to determine what part of the window is being hovered here. This
// is absolutely critical to making sure Snap Layouts (GH#9443) works!
return _dragBarNcHitTest(til::point{ GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam) });
// return _dragBarNcHitTest(til::point{ GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam) });
LRESULT lResult = 0;
if (!DwmDefWindowProc(GetHandle(), message, wparam, lparam, &lResult))
{
return _dragBarNcHitTest(til::point{ GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam) });
}
else
{
return lResult;
}
}
break;
@@ -170,8 +192,12 @@ LRESULT NonClientIslandWindow::_InputSinkMessageHandler(UINT const message,
{
case HTTOP:
case HTCAPTION:
case HTMAXBUTTON:
case HTMINBUTTON:
case HTCLOSE:
default:
{
_titlebar.ReleaseButtons();
// _titlebar.ReleaseButtons();
// Pass caption-related nonclient messages to the parent window.
// Make sure to do this for the HTTOP, which is the top resize
@@ -179,43 +205,66 @@ LRESULT NonClientIslandWindow::_InputSinkMessageHandler(UINT const message,
auto parentWindow{ GetHandle() };
return SendMessage(parentWindow, message, wparam, lparam);
}
case HTMINBUTTON:
case HTMAXBUTTON:
case HTCLOSE:
_titlebar.HoverButton(static_cast<winrt::TerminalApp::CaptionButton>(wparam));
break;
default:
_titlebar.ReleaseButtons();
}
// case HTMAXBUTTON:
// {
// // TODO! Fake out the y coordinate here for the maximize button, so
// // as to force DWM to think we've hovered on the singular visible
// // pixel of the maximize button, rather than where we are, which is
// // not over the caption button that DWM drew.
// til::point original = til::point{ GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam) };
// til::rect windowRect = til::rect{ GetWindowRect() };
// // auto xPos = 0xffff0000 & lparam;
// auto yPos = windowRect.top + 8;
// // lparam = (xPos | yPos);
// lparam = MAKELONG(GET_X_LPARAM(lparam), yPos);
// til::point converted = til::point{ GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam) };
// converted;
// auto a = 0;
// a++;
// a;
// // TODO! This didn't work at all. But _dragBarNcHitTest DOES
// // successfully return the right thing. There must be some extra
// // logic in the DWM side that's checking "Hey I see you said you're
// // on the maximize button but the thing is, you're not"
// If we haven't previously asked for mouse tracking, request mouse
// tracking. We need to do this so we can get the WM_NCMOUSELEAVE
// message when the mouse leave the titlebar. Otherwise, we won't always
// get that message (especially if the user moves the mouse _real
// fast_).
if (!_trackingMouse &&
(wparam == HTMINBUTTON || wparam == HTMAXBUTTON || wparam == HTCLOSE))
{
TRACKMOUSEEVENT ev{};
ev.cbSize = sizeof(TRACKMOUSEEVENT);
// TME_NONCLIENT is absolutely critical here. In my experimentation,
// we'd get WM_MOUSELEAVE messages after just a HOVER_DEFAULT
// timeout even though we're not requesting TME_HOVER, which kinda
// ruined the whole point of this.
ev.dwFlags = TME_LEAVE | TME_NONCLIENT;
ev.hwndTrack = _dragBarWindow.get();
ev.dwHoverTime = HOVER_DEFAULT; // we don't _really_ care about this.
LOG_IF_WIN32_BOOL_FALSE(TrackMouseEvent(&ev));
_trackingMouse = true;
}
break;
// // [[fallthrough]]
// }
// case HTMINBUTTON:
// case HTCLOSE:
// _titlebar.HoverButton(static_cast<winrt::TerminalApp::CaptionButton>(wparam));
// break;
// default:
// _titlebar.ReleaseButtons();
// }
case WM_NCMOUSELEAVE:
case WM_MOUSELEAVE:
// When the mouse leaves the drag rect, make sure to dismiss any hover.
_titlebar.ReleaseButtons();
_trackingMouse = false;
break;
// // If we haven't previously asked for mouse tracking, request mouse
// // tracking. We need to do this so we can get the WM_NCMOUSELEAVE
// // message when the mouse leave the titlebar. Otherwise, we won't always
// // get that message (especially if the user moves the mouse _real
// // fast_).
// if (!_trackingMouse &&
// (wparam == HTMINBUTTON || wparam == HTMAXBUTTON || wparam == HTCLOSE))
// {
// TRACKMOUSEEVENT ev{};
// ev.cbSize = sizeof(TRACKMOUSEEVENT);
// // TME_NONCLIENT is absolutely critical here. In my experimentation,
// // we'd get WM_MOUSELEAVE messages after just a HOVER_DEFAULT
// // timeout even though we're not requesting TME_HOVER, which kinda
// // ruined the whole point of this.
// ev.dwFlags = TME_LEAVE | TME_NONCLIENT;
// ev.hwndTrack = _dragBarWindow.get();
// ev.dwHoverTime = HOVER_DEFAULT; // we don't _really_ care about this.
// LOG_IF_WIN32_BOOL_FALSE(TrackMouseEvent(&ev));
// _trackingMouse = true;
// }
// break;
}
// case WM_NCMOUSELEAVE:
// case WM_MOUSELEAVE:
// // When the mouse leaves the drag rect, make sure to dismiss any hover.
// _titlebar.ReleaseButtons();
// _trackingMouse = false;
// break;
// NB: *Shouldn't be forwarding these* when they're not over the caption
// because they can inadvertently take action using the system's default
@@ -238,44 +287,45 @@ LRESULT NonClientIslandWindow::_InputSinkMessageHandler(UINT const message,
auto parentWindow{ GetHandle() };
return SendMessage(parentWindow, message, wparam, lparam);
}
// The buttons won't work as you'd expect; we need to handle those
// ourselves.
case HTMINBUTTON:
case HTMAXBUTTON:
case HTCLOSE:
_titlebar.PressButton(static_cast<winrt::TerminalApp::CaptionButton>(wparam));
break;
}
return 0;
// // The buttons won't work as you'd expect; we need to handle those
// // ourselves.
// case HTMINBUTTON:
// case HTMAXBUTTON:
// case HTCLOSE:
// _titlebar.PressButton(static_cast<winrt::TerminalApp::CaptionButton>(wparam));
// break;
// }
// return 0;
case WM_NCLBUTTONUP:
// Manual handling for mouse RELEASES in the drag bar. If it's in a
// caption button, then manually handle what we'd expect for that button.
//
// If it's not in a caption button, then just forward the message along
// to the root HWND.
switch (wparam)
{
case HTTOP:
case HTCAPTION:
{
// Pass caption-related nonclient messages to the parent window.
// The buttons won't work as you'd expect; we need to handle those ourselves.
auto parentWindow{ GetHandle() };
return SendMessage(parentWindow, message, wparam, lparam);
}
break;
// If we do find a button, then tell the titlebar to raise the same
// event that would be raised if it were "tapped"
case HTMINBUTTON:
case HTMAXBUTTON:
case HTCLOSE:
_titlebar.ReleaseButtons();
_titlebar.ClickButton(static_cast<winrt::TerminalApp::CaptionButton>(wparam));
case WM_NCLBUTTONUP:
// Manual handling for mouse RELEASES in the drag bar. If it's in a
// caption button, then manually handle what we'd expect for that button.
//
// If it's not in a caption button, then just forward the message along
// to the root HWND.
switch (wparam)
{
case HTTOP:
case HTCAPTION:
{
// Pass caption-related nonclient messages to the parent window.
// The buttons won't work as you'd expect; we need to handle those ourselves.
auto parentWindow{ GetHandle() };
return SendMessage(parentWindow, message, wparam, lparam);
}
break;
// // If we do find a button, then tell the titlebar to raise the same
// // event that would be raised if it were "tapped"
// case HTMINBUTTON:
// case HTMAXBUTTON:
// case HTCLOSE:
// _titlebar.ReleaseButtons();
// _titlebar.ClickButton(static_cast<winrt::TerminalApp::CaptionButton>(wparam));
// break;
}
return 0;
}
return 0;
// Make sure to pass along right-clicks in this region to our parent window
// - we don't need to handle these.
@@ -506,8 +556,8 @@ void NonClientIslandWindow::_OnMaximizeChange() noexcept
const auto isIconified = WI_IsFlagSet(windowStyle, WS_ICONIC);
const auto state = _isMaximized ? winrt::TerminalApp::WindowVisualState::WindowVisualStateMaximized :
isIconified ? winrt::TerminalApp::WindowVisualState::WindowVisualStateIconified :
winrt::TerminalApp::WindowVisualState::WindowVisualStateNormal;
isIconified ? winrt::TerminalApp::WindowVisualState::WindowVisualStateIconified :
winrt::TerminalApp::WindowVisualState::WindowVisualStateNormal;
try
{
@@ -860,7 +910,9 @@ void NonClientIslandWindow::_UpdateFrameMargins() const noexcept
// We can't set it to all 0's unfortunately.
if (_borderless)
{
margins.cyTopHeight = 1;
// margins.cyTopHeight = 1;
// margins.cyTopHeight = static_cast<int>(_titlebar.ActualHeight());
margins.cyTopHeight = 40;
}
else if (_GetTopBorderHeight() != 0)
{
@@ -885,6 +937,9 @@ void NonClientIslandWindow::_UpdateFrameMargins() const noexcept
margins.cyTopHeight = -frame.top;
}
// // For debugging: Manually set the top fram height to 16 px. Snap layouts only works in that space, apparently.
// margins.cyTopHeight = 16;
// Extend the frame into the client area. microsoft/terminal#2735 - Just log
// the failure here, don't crash. If DWM crashes for any reason, calling
// THROW_IF_FAILED() will cause us to take a trip upstate. Just log, and
@@ -905,6 +960,7 @@ void NonClientIslandWindow::_UpdateFrameMargins() const noexcept
WPARAM const wParam,
LPARAM const lParam) noexcept
{
// DwmDefWindowProc(GetHandle(), message, wParam, lParam, &lRet)
switch (message)
{
case WM_SETCURSOR:
@@ -956,8 +1012,14 @@ void NonClientIslandWindow::_UpdateFrameMargins() const noexcept
return 0;
}
const auto topBorderHeight = _GetTopBorderHeight();
if (ps.rcPaint.left == ps.rcPaint.right && ps.rcPaint.top == ps.rcPaint.bottom)
{
return 0;
}
// TODO! NOTE: This seemingly does nothing anymore.
auto topBorderHeight = _GetTopBorderHeight();
topBorderHeight = 40;
if (ps.rcPaint.top < topBorderHeight)
{
auto rcTopBorder = ps.rcPaint;
@@ -1130,3 +1192,8 @@ bool NonClientIslandWindow::_IsTitlebarVisible() const
{
return !(_fullscreen || _borderless);
}
void NonClientIslandWindow::SetTitlebarBackground(winrt::Windows::UI::Xaml::Media::Brush brush)
{
_titlebar.Background(brush);
}

View File

@@ -47,6 +47,8 @@ public:
void SetTitlebarContent(winrt::Windows::UI::Xaml::UIElement content);
void OnApplicationThemeChanged(const winrt::Windows::UI::Xaml::ElementTheme& requestedTheme) override;
void SetTitlebarBackground(winrt::Windows::UI::Xaml::Media::Brush brush);
private:
std::optional<COORD> _oldIslandPos;
@@ -65,7 +67,7 @@ private:
bool _trackingMouse{ false };
[[nodiscard]] static LRESULT __stdcall _StaticInputSinkWndProc(HWND const window, UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept;
[[nodiscard]] LRESULT _InputSinkMessageHandler(UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept;
[[nodiscard]] LRESULT _InputSinkMessageHandler(UINT const message, WPARAM const wparam, LPARAM lparam) noexcept;
void _ResizeDragBarWindow() noexcept;

View File

@@ -64,7 +64,9 @@ Abstract:
#include <winrt/Windows.UI.Core.h>
#include <winrt/Windows.UI.Xaml.Controls.h>
#include <winrt/Windows.UI.Xaml.Controls.Primitives.h>
#include <winrt/Windows.ui.xaml.data.h>
#include <winrt/Windows.ui.xaml.media.h>
#include <winrt/Windows.ui.xaml.data.h>
#include <winrt/Windows.ApplicationModel.h>
#include <winrt/Windows.ApplicationModel.Resources.Core.h>
#include <winrt/Windows.UI.Composition.h>

View File

@@ -87,31 +87,43 @@ std::string Utils::ColorToHexString(const til::color color)
// the correct format, throws E_INVALIDARG
til::color Utils::ColorFromHexString(const std::string_view str)
{
THROW_HR_IF(E_INVALIDARG, str.size() != 7 && str.size() != 4);
THROW_HR_IF(E_INVALIDARG, str.size() != 9 && str.size() != 7 && str.size() != 4);
THROW_HR_IF(E_INVALIDARG, str.at(0) != '#');
std::string rStr;
std::string gStr;
std::string bStr;
std::string aStr;
if (str.size() == 4)
{
rStr = std::string(2, str.at(1));
gStr = std::string(2, str.at(2));
bStr = std::string(2, str.at(3));
aStr = "ff";
}
else
else if (str.size() == 7)
{
rStr = std::string(&str.at(1), 2);
gStr = std::string(&str.at(3), 2);
bStr = std::string(&str.at(5), 2);
aStr = "ff";
}
else if (str.size() == 9)
{
// #aarrggbb
aStr = std::string(&str.at(1), 2);
rStr = std::string(&str.at(3), 2);
gStr = std::string(&str.at(5), 2);
bStr = std::string(&str.at(7), 2);
}
const auto r = gsl::narrow_cast<BYTE>(std::stoul(rStr, nullptr, 16));
const auto g = gsl::narrow_cast<BYTE>(std::stoul(gStr, nullptr, 16));
const auto b = gsl::narrow_cast<BYTE>(std::stoul(bStr, nullptr, 16));
const auto a = gsl::narrow_cast<BYTE>(std::stoul(aStr, nullptr, 16));
return til::color{ r, g, b };
return til::color{ r, g, b, a };
}
// Routine Description: