terminal/doc/specs/#3062 - Appearance configur...

6.0 KiB

author created on last updated issue id
Pankaj Bhojwani, pabhojwa@microsoft.com 2020-11-20 2021-2-5

Appearance configuration objects for profiles

Abstract

This spec outlines how we can support 'configuration objects' in our profiles, which will allow us to render differently depending on the state of the control. For example, a control can be rendered differently if it's focused as compared to when it's unfocused.

Inspiration

Reference: #3062

Users want there to be a more visible indicator than the one we have currently for which pane is focused and which panes are unfocused. This change would grant us that feature.

Solution Design

The implementation design for appearance config objects centers around the recent change where inheritance was added to the TerminalSettings class in the Terminal Settings Model - i.e. different TerminalSettings objects can inherit from each other. The reason for this change was that we did not want a settings reload to erase any overrides TermControl may have made to the settings during runtime. By instead passing a child of the TerminalSettings object to the control, we can change the parent of the child during a settings reload without the overrides being erased (since those overrides live in the child).

The idea behind unfocused appearance configurations is similar. We will pass in another TerminalSettings object to the control, which is simply a child that already has some overrides in it. When the control gains or loses focus, it simply switches between the two settings objects appropriately.

Allowed parameters

For now, these states are meant to be entirely appearance-based. So, not all parameters which can be defined in a Profile can be defined in this new object (for example, we do not want parameters which would cause a resize in this object.) Here is the list of parameters we will allow:

  • Anything regarding colors: colorScheme, foreground, background, cursorColor etc
  • Anything regarding background image: path, opacity, alignment, stretchMode
  • cursorShape

We may wish to allow further parameters in these objects in the future (like bellStyle?). The addition of further parameters can be discussed in the future and is out of scope for this spec.

Inheritance

The inheritance model can be thought of as an 'all-or-nothing' approach in the sense that the unfocusedAppearance object is considered as a single setting instead of an object with many settings. We have chosen this model because it is cleaner and easier to understand than the alternative, where each setting within an unfocusedAppearance object has a parent from which it obtains its value.

Note that when TerminalApp initializes a control, it creates a TerminalSettings object for that profile and passes the control a child of that object (so that the control can store overrides in the child, as described earlier). If an unfocused config is defined in the profile (or in globals/profile defaults), then TerminalApp will create a child of that child, put the relevant overrides in it, and pass that into the control as well. Thus, the inheritance of any undefined parameters in the unfocused config will be as follows:

  1. The unfocused config specified in the profile (or in globals/profile defaults)
  2. Overrides made by the terminal control
  3. The parent profile

UI/UX Design

Users will be able to add a new setting to their profiles that will look like this:

"unfocusedAppearance":
{
    "colorScheme": "Campbell",
    "cursorColor": "#888",
    "cursorShape": "emptyBox",
    "foreground": "#C0C0C0",
    "background": "#000000"
}

When certain appearance settings are changed via OSC sequences (such as the background color), only the focused/regular appearance will change and the unfocused one will remain unchanged. However, since the unfocused settings object inherits from the regular one, it will still apply the change (provided it does not define its own value for that setting).

Capabilities

Accessibility

Does not affect accessibility.

Security

Does not affect security.

Reliability

This is another location in the settings where parsing/loading the settings may fail. However, this is the case for any new setting we add so I would say that this is a reasonable cost for this feature.

Compatibility

Should not affect compatibility.

Performance, Power, and Efficiency

Rapidly switching between many panes, causing several successive appearance changes in a short period of time, could potentially impact performance. However, regular/reasonable pane switching should not have a noticeable effect.

Potential Issues

Inactive tabs will be 'rendered' in the background with the UnfocusedRenderingParams object, we need to make sure that switching to an inactive tab (and so causing the renderer to update with the 'normal' parameters) does not cause the window to flash/show a jarring indicator that the rendering values changed.

Future considerations

We will need to decide how this will look in the settings UI.

We may wish to add more states in the future (like 'elevated'). When that happens, we will need to deal with how these appearance objects can scale/layer over each other. We had a lot of discussion about this and could not find a suitable solution to the problem of multiple states being valid at the same time (like unfocused and elevated). This, along with the fact that it is uncertain if there even will be more states we would want to add led us to the conclusion that we should only support the unfocused state for now, and come back to this issue later. If there are no more states other than unfocused and elevated, we could allow combining them (like having an 'unfocused elevated' state). If there are more states, we could do the implementation as an extension rather than inherently supporting it.

Resources