Skip to content

Commit

Permalink
mica spec
Browse files Browse the repository at this point in the history
  • Loading branch information
zadjii-msft committed Feb 15, 2022
1 parent bb14d69 commit a71b8a7
Show file tree
Hide file tree
Showing 4 changed files with 242 additions and 10 deletions.
169 changes: 169 additions & 0 deletions doc/specs/#3327 - Application Theming/#10509 - Mica.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
---
author: Mike Griese @zadjii-msft
created on: 2022-02-15
last updated: 2022-02-15
issue id: #10509
---


# Mica in the Terminal

## Abstract

This document serves as a companion doc to the [Theming Spec], rather than a
spec on it's own. The context of broader application-level theming support is
necessary to undertand the big picture of the designs in this discussion.


This spec is intended to help understand the problem space of adding [Mica] to
the Windows Terminal. Introduced in Windows 11, Mica is a new type of material
that incorporates theme and desktop wallpaper to paint the background of
windows. The effect results in a blurred, transparency-like effect, quite
similar to [Acrylic]. However, the technical limitations of Mica make it more
complicated to integrate seemlessly with the Terminal experience.

## Background

Mica is a material that can only be applied to the root of the UI tree, and
applies to the entire background surface. It's recommended to be used at the
`Page` level, in place of a solid brush like
`ApplicationPageBackgroundThemeBrush`. If the developer wants a surface within
the page to have a Mica background, they need to make sure to have that element
(and all elements behind it up until the `Page`) have a `Transparent`
background, so that Mica will be visible through the elements.

This is contrasted with something like Acrylic, where the acrylic effect is
specified at the Element layer itself. An element can request having a
`HostBackdrop` brush for its background, and the element will have the Acrylic
effect regardless of the structure of the rest of the elements in the UI tree.

Another important use case here is "Vintage Transparency" (or "unblurred
transparency"), which is an unblurred transparency effect for the Terminal
window. This is achieved with the `TransparentBackground` API, which enables the
Terminal to disable the emergency backstop of the XAML Island. When that's
enabled, controls that are transparent will be blended, unblurred, with whatever
is visible behind the window. This works because the entire tree of the Terminal
window underneath the `TermControl`s are `Transparent`, all the way up to the
window itself.

Right now, the Terminal exposes three settings<sup>[[1]](#footnote-1)</sup>:
* Background color
* Background Opacity
* Whether the user would like to enable acrylic or not

These settings are exposed at the "Profile"<sup>[[2]](#footnote-2)</sup> level.
Properties on a profile are roughly considered to be "what the terminal control
will look like when I run this settings profile". Users can have one profile
with acrylic, one without, and open [Panes] with these profiles side-by-side in
the Terminal. It's entirely possible that a user would have both a pane with and
acrylic background, and one with an unblurred background in the same window.



### User Stories

* The Terminal should be able to have Mica in the title bar, behind the tabs.
* Users will want Mica in the control area, as well as in the titlebar
* Users may want Mica in the control, but with a solid titlebar, or an accent
colored title bar, or an acrylic one...
* Users will want mica in the titlebar with other effects (acrylic, vintage
transparency) in the control area


This is where things get complicated. Given that a control can choose what tyoe
of material it has now, users would likely expect to be able to choose between
acrylic, unblurred transparency, or Mica. However, Mica can only be applied at
the root of the window. It's applied behind everything else in the window. From
an implementation standpoint, Mica is a window-level property, not a control
level one. If we want to have Mica under one control, we need to enable it for
the _whole window_. If we enable Mica for the whole window, that would
simultaneously prevent Vintage Transparency from working as expected. This is
because the semi-transparent controls would no longer have a fully transparent
window background to sit on top of - they'd be blended instead with the Mica
background behind the window.

## Solution design

### Mica for `TermControl`s
If we make enabling Mica for the control a per-profile setting, I believe that
will lead to greater user confusion. It would result in "spooky action at a
distance", where creating any pane with Mica would force the entire window to
have a Mica background. This would change the appearance of any other unburred
transparent panes in the window, causing them to also be subjected to the Mica
treatment as well.

**Proposal**: create a window-level theme property `window.useMica` (or
similar), which will enable Mica for the entire window. When enabled, users can
use a fully transparent, unblurred background for their profile to acheive the
Mica effect within the control. When enabled, users **won't** be able to see
through to the desktop with any vintage opacity settings.

I believe this is the most acceptable way to expose Mica to our users without
"spooky action at a distance".

An example of what mica in the control area might look like:

![Mica in the TermControl](./mica-in-control-000.png)

### Mica in the titlebar

To achieve Mica in the titlebar, we'll similarly need to allow users to set the
titlebar area to totally transparent, to allow the mica behind the window to be
visible. A simple theme to achieve that might look like:

```jsonc
{
"theme": "My Mica Titlebar Theme",
"themes": [
{
"name": "My Mica Titlebar Theme",
"window.useMica": true, // Use mica behind the window
"tabRow.background": "#00000000", // Make the TabView Transparent
}
]
}
```

## Considered implementations

* We experimented with a new DWM API in SV2 which should enable us to set the
background of our window to Mica. This did seem to work for the root window.
It however, did not seem to work for the "drag window", the child HWND which
we use to intercept nonclient messages in our titlebar area. Apparently, that
API does not work at all for `WS_CHILD` windows, by design. This unfortunately
prevents us from allowing Mica only in the titlebar area, without also
applying it to the rest of the main window.

## Potential Issues

This is not a particularly ergonomic design. From a UX perspective, the user
needs to enable one setting in the UI to enable Mica, and then go to profile
settings to set the profile to _transparent_ for each of the profiles they want
with Mica. That's not very intuitive by any means.



## Future considerations


## Resources


### Footnotes

<a name="footnote-1"><a>[1]: For simplicity of the spec, I'm ignoring the
background image settings. I'm also ignoring the small quirk where (at the time
of writing), vintage opacity doesn't work on Windows 10. That creates some weird
quirks where acrylic is always enabled if the user wants transparency on Windows
10. A full discussion of this would only serve to complicate what is
fundamentally a Windows 11-centric discussion.

<a name="footnote-2"><a>[2]: We're also gonna leave out a discussion of focused
& unfocused "appearance" setting objects, again for brevity.

[Theming Spec]: ./%233327%20-%20Application%20Theming.md
[Mica]: https://docs.microsoft.com/en-us/windows/apps/design/style/mica
[Acrylic]: https://docs.microsoft.com/en-us/windows/apps/design/style/acrylic
[Panes]: https://docs.microsoft.com/en-us/windows/terminal/panes
[#3327]: https://github.com/microsoft/terminal/issues/3327
[#10509]: https://github.com/microsoft/terminal/issues/10509
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,16 @@ issue id: #3327
---


TODOS:
* Mica. The whole app needs to be transparent for that. It'll affect the vintage opacity setting. Must be careful.
TODO!S:
* Allow alpha in these colors. Like, I want the tabs to be `#10808080` lighter than the tabrow which is acrylic, `#40102030`
- Oh my, I already did that didn't I
* whole application window BG images, a la that one post in the theming thread
* `window.roundedCorners` true/false
* How do themes play with different window title settings? (different themes for different windows. `_quake` esp.))
* any clever ideas for elevated themes?
* tab.bottomCornerRadius? or is tab.cornerRadius a "1" = all 1, "1, 2" = tops 1, bottoms 2 kinda situation


# Spec Title
# Application Theming

## Abstract

Expand All @@ -33,7 +31,6 @@ themes can be more than just different color palettes for the editor - these
themes can control the appearance of a variety of UI elements of the VsCode
window.


## Solution Design

### Requested Functionality ("User Stories")
Expand Down Expand Up @@ -142,7 +139,7 @@ Take for example the following settings excerpt:
}
```

> **TODO FOR DISCUSSION**: I've given both a `tab.<property>` and a
> **TODO! FOR DISCUSSION**: I've given both a `tab.<property>` and a
> `tab<Property>` style here, for comparison. At the time of writing, I'm unsure
> of which is better. I'll be using `<element>.<property>` for the remainder of
> the doc.
Expand Down Expand Up @@ -194,6 +191,8 @@ control the UI.
property. This can be one of `light`, `dark` or `system`. This controls how
XAML fundamentally styles UI elements. If not provided, will use the default
value "system", which will use whatever the system's default theme is.
* `window.roundedCorners`: A boolean, to control whether the window has rounded
corners on Windows 11.

#### Theme Colors

Expand All @@ -207,10 +206,10 @@ be one of:
terminal instance.
* `key:SomeXamlKey` to try and look `SomeXamlKey` up from our resources as a
`Color`, and use that color for the value.
- TODO DISCUSSION: Does anyone want this?
- **TODO! DISCUSSION**: Does anyone want this?
- is `accent` just `key:SystemAccentColor`? If it is, is it a reasonable
alias that we'd want to provide anyways?
- TODO DISCUSSION: PR[#5280] suggested `{ "key": "SomeResourceKey" }` for
- **TODO! DISCUSSION**: PR[#5280] suggested `{ "key": "SomeResourceKey" }` for
string resources, should we use that format for colors like this as well?

This will enable users to not only provide custom colors, but also use the
Expand Down Expand Up @@ -410,7 +409,7 @@ confusing, but they have that freedom.

## UI/UX Design

[TODO]: # TODO: We should include more mockups here. That would be nice.
[TODO!]: # TODO: We should include more mockups here. That would be nice.

![Tab matches Terminal background](Tab-Matches-Terminal-Color-000.png)
_fig 1_: Using a tab color set to "terminalBackground". The Windows PowerShell
Expand All @@ -424,6 +423,14 @@ _fig 2_: Using an acrylic titlebar color, with a tab color set to
_fig 3_: Using an acrylic terminal background, and the titlebar color is set to
"terminalBackground"

![Whole window background image](whole-window-background-000.png) _fig
4_: Using a single image as the background for the window, with a transparent
tab row, and rounded bottoms on the TabViewItems. Courtesy of
[@Shomnipotence](https://github.com/microsoft/terminal/issues/3327#issuecomment-765493313)


[TODO!]: # TODO: Settings UI mocks? These pretty substantially affect the UI.
<!-- We probably need to expose them in the UI in some way, and not just leave them as "power user settings" -->

## Capabilities

Expand Down Expand Up @@ -457,6 +464,9 @@ This change should not have any particular reliability concerns.
The biggest compatibility concern is regarding the existing values for the
`theme` property, which is addressed above.

[TODO!]: # TODO: Deprecating the current titlebar acrylic setting, or totally overriding in theme.


### Performance, Power, and Efficiency

## Potential Issues
Expand All @@ -477,6 +487,55 @@ Windows Terminal". Is this something we're really all that concerned about
though? If this is something users want (it is), then shouldn't that be what
matters?

### Light & dark mode theming

One request that comes up with frequency is the ability to change the color
scheme of a profile automatically based on the system theme. Many users have
scripts that automatically change between light and dark theme in the OS based
on time of day.

One thing this design does not do well is account for such theme-switching
scenarios. This design assumes a static set of colors for a whole Terminal
theme, regardless of whatever `window.applicationTheme` is set to. Should the
user leave `window.applicationTheme` set to `system`, it's entirely likely that
they would like the rest of their colors to automatically update to match.

[TODO!]: # TODO!

_Terrible ideas_:
* allow the user to set different themes for different OS themes. Something like
`"theme": { "light": "My Light Theme", "dark": "My Dark Theme" }`
* Allow the user to set their own brushes as part of a theme? So like,
```jsonc
{
"name": "My theme aware theme",
"brushes": {
"light": {
"Foo": "#ff0000"
},
"dark": {
"Foo": "#00ff00"
}
},
"window.applicationTheme": "system",
"tabRow.background": "key:Foo",
}
```

### Admin window themes

[TODO!]: # TODO!

Same idea as the light vs dark mode theme ideas. How should users be able to
style admin vs regular windows?

## Addenda

This spec also has a follow-up spec which elaborates on the comlpexites of Mica
in the Terminal. Please also refer to:

* [Mica in the Terminal](./%2310509%20-%20Mica.md)

## Future considerations

* Mentioned in [#7005] was the idea of shipping a default theme that had values
Expand All @@ -489,6 +548,10 @@ matters?
"tabRow.background": "accent",
},
```
* Applications should be able to install themes as fragments.
- We probably shouldn't allow layering for fragment themes - don't want
`foo.exe` installing a `light` theme that totally overrides the built-in
one. Right? **TODO! DISCUSSION**

#### Theming v2 Properties

Expand All @@ -503,7 +566,7 @@ matters?
tab row and the Terminal panes beneath it. This border doesn't exist
currently.
* `tabRow.underlineColor`: Controls the color of the aforementioned underline

* `DWMWA_BORDER_COLOR`: That's not super well documented but the name is interesting for sure.

<!-- Footnotes -->

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit a71b8a7

Please sign in to comment.