Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial Theme support #12992

Merged
merged 70 commits into from
Jul 7, 2022
Merged

Initial Theme support #12992

merged 70 commits into from
Jul 7, 2022

Conversation

zadjii-msft
Copy link
Member

@zadjii-msft zadjii-msft commented Apr 27, 2022

⚠️ targeting 1.15

Summary of the Pull Request

Adds support for Themes, a new type of customization for the Terminal. Themes allow the user to customize elements of the Terminal window itself. In this first iteration, this PR adds support for two main properties:

  • enabling Mica as the window backdrop
  • changing the tab row color (read: changing the titelbar color)

These represent the most important asks of theming in the Terminal. The properties added in this PR are:

  • Theme color variants:
    • "#rrggbb" or "#aarrggbb"
    • "accent"
    • "terminalBackground"
  • Properties (listed here in dot notation, but implemented as sub-objects)
    • tabRow.background: accepts a ThemeColor (above)
    • window.applicationTheme: accepts one of {"system", "light", "dark"}
    • window.useMica: accepts a boolean, defaults to false.

References

PR Checklist

Detailed Description of the Pull Request / Additional comments

--> GO READ #12530 <--

Seriously.

These themes aren't customizable in the SUI currently. You can change the active theme, and the UI will show all of the defined themes, but they're not editable there.

They don't layer. You'll need to define your own themes.

Thay can't come from fragments. This is a really cool future idea, but not implemented in this v0.

The sub objects have some gnarly macros to generate a lot of the serialization code for you.

TODOs

  • I still have yet to establish what the accent color algorithm is. This might be proprietary and require a ThemeHelpers workaround.
  • Make sure terminalBackground & the SUI result in something sensible
  • Make sure runtime BG changes work with terminalBackground. One time, they didn't. printf "\x1b]11;rgb:ff/00/ff\x07"
  • Acrylic Terminal BG's look weird, like, the opacity is always 50% or something. And the tab row looks all wrong then.

Validation Steps Performed

This is the blob I've been testing with:

    // "useAcrylicInTabRow": true,
    "theme": "my dark",
    // "theme": "Edge",
    "theme": "orangey",
    "theme": "WHITE",
    // "theme": "terminal",
    "themes": [
        {
            "name": "my dark",
            "window": {
                "applicationTheme": "dark",
                "useMica": true,
            },
            "tabRow": {
                "background": "#00000000",
            },
        },
        {
            "name": "Edge",
            "tabRow": { "background": "accent" },
            "window": { "applicationTheme": "system" }
        },
        {
            "name": "orangey",

            "window": {
                "applicationTheme": "light",
                "useMica": true,
            },
            "tabRow": {
                "background": "#ff8800",
            },
        },
        {
            "name": "WHITE",
            "window": {
                "applicationTheme": "dark",
                "useMica": true,
            },
            "tabRow": {
                "background": "#FFFFFF",
            },
        },
        {
            "name": "terminal",

            "window": {
                "applicationTheme": "dark",
                "useMica": false,
            },
            "tabRow": {
                "background": "terminalBackground",
            },
        },
    ]

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.
@ghost

This comment was marked as resolved.

@zadjii-msft zadjii-msft removed Needs-Author-Feedback The original author of the issue/PR needs to come back and respond to something No-Recent-Activity This issue/PR is going stale and may be auto-closed without further activity. labels Jun 8, 2022
@zadjii-msft
Copy link
Member Author

shhh bot, I was cleaning up pee all of last week

Copy link
Member

@carlos-zamora carlos-zamora left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

YOLO. Best to get this in at the beginning of the cycle and start selfhosting this. :)

}

const auto theme = _settings.GlobalSettings().CurrentTheme();
auto requestedTheme{ theme.RequestedTheme() };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
auto requestedTheme{ theme.RequestedTheme() };
const auto requestedTheme{ theme.RequestedTheme() };

I think?


til::color bgColor = backgroundSolidBrush.Color();

if (_settings.GlobalSettings().UseAcrylicInTabRow())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Long-term, should we move useAcrylicInTabRow to be a part of the theme itself? If that's the case, (in a follow up) we should probably add deserialization logic to take this setting and write it as a part of themes (kinda like we did with the font object change).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW if we do that, we need some way to emit a completely new theme for the user, because they are not allowed to edit the system themes

else if (theme.TabRow() && theme.TabRow().Background())
{
const auto tabRowBg = theme.TabRow().Background();
const auto terminalBrush = [this]() -> Media::Brush {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

General question: when should we capture this vs &?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typically I've found it best to try and capture as little as possible. There's a lot going on in this method, but the only thing we really need is this. If there were a bunch of other locals we needed in here too, then just go for &. That's not really based on any specific insight, just my own preference.

In anything that's gonna happen async, both this and & are bad.

@zadjii-msft zadjii-msft merged commit 07d58a8 into main Jul 7, 2022
@zadjii-msft zadjii-msft deleted the dev/migrie/fhl/theming-2022-prototype branch July 7, 2022 11:54
zadjii-msft added a commit that referenced this pull request Jul 7, 2022
## Summary of the Pull Request

Adds support for the `tab.background` property to themes. This is also a ThemeColor, so it accepts, colors, `accent`, and `terminalBackground`, just like everything else.

## References
* See #3327 
* ⚠️ targets #12992 ⚠️


## PR Checklist
* [x] Closes #702
* [x] I work here
* [ ] Tests added/passed
* [n/a] Requires documentation to be updated - YUP

## Detailed Description of the Pull Request / Additional comments

I apparently left behing an optional color in TerminalTab for theme colors some time ago, just never used it. Crazy, huh?

## Validation Steps Performed

gifs below
ghost pushed a commit that referenced this pull request Jul 7, 2022
Adds `tabRow.unfocusedBackground` to the theme properties.

When provided, the window will use this ThemeColor as the color of the tab row when the window is inactive. 

When omitted, the window will fall back to the default tab row color, `{"key": "TabViewBackground"}` from our App.xaml.

* [ ] tests added.
* [x] Closes #4862
* [ ] Needs a whole pile of docs updates, which we'll do at the end here.


This actually helped validate #12992 quite a bit. I found a bunch of bugs concerning null colors, null objects. Json parsing is hard 😛
rStr = std::string(&str.at(1), 2);
gStr = std::string(&str.at(3), 2);
bStr = std::string(&str.at(5), 2);
aStr = "ff";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't love that we force a string parser to parse ff just to get 255... ;P

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,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

XAML in the settings model -- this will cause trouble for a consumer like the shell extension in the future.

};

#undef THEME_SETTINGS_INITIALIZE
#undef THEME_SETTINGS_COPY
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need to undef COPY_THEME...?


std::string TypeDescription() const
{
return "ThemeColor (#rrggbb, #rgb, #aarrggbb, accent, terminalBackground)";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isn't it rrggbbaa?

return nullptr;
}
const auto string{ Detail::GetStringView(json) };
if (string == "accent")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: prefer declaring these magic constant values in the class body and referencing them later


if (_settings.GlobalSettings().UseAcrylicInTabRow())
{
const til::color backgroundColor = backgroundSolidBrush.Color();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You marked it as resolved... but the line of code is still here.

Comment on lines +4132 to +4134
_activated = activated;
_updateTabRowColors();
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so _activated is ignored?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, this guy snuck into the parent branch. It was used in the unfocused titlebar branch.

return val;
}

static til::color _getAccentColorForTitlebar()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we reload this when the accent color changes?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AMAZINGLY, YES WE DO

\
std::string TypeDescription() const \
{ \
return "name (You should never see this)"; \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lol this will actually say the word "name" since it's not in a macro-stringify expression

{
auto result = winrt::make_self<Theme>();

if (json.isString())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we control the entire themes array, from its inception to its death. Who would put a string in it?

@ghost ghost removed the Needs-Second It's a PR that needs another sign-off label Jul 7, 2022
This was referenced Jul 7, 2022
ghost pushed a commit that referenced this pull request Jul 12, 2022
The main fix here is for the caption button colors. If you had a dark OS/app theme, and a light titlebar, we'd end up with light glyphs, so the caption buttons would be impossible to find.

There's also a pile of nits from #12992 in here. Probably enough to close #13456 out, but I'll let Dustin be the judge. 

Filing today, to get in for 1.16 selfhost (@DHowett)
@ghost
Copy link

ghost commented Sep 13, 2022

🎉Windows Terminal Preview v1.16.252 has been released which incorporates this pull request.:tada:

Handy links:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Settings Issues related to settings and customizability, for console or terminal Area-Theming Anything related to the theming of elements of the window Issue-Feature Complex enough to require an in depth planning process and actual budgeted, scheduled work. Issue-Task It's a feature request, but it doesn't really need a major design. Product-Terminal The new Windows Terminal.
Projects
None yet
4 participants