Add support for branch- and branding-based feature flagging (#10361)
This pull request implements a "feature flagging" system that will let
us turn Terminal and conhost features on/off by branch, "release" status
or branding (Dev, Preview, etc.).
It's loosely modelled after the Windows OS concept of "Velocity," but
only insofar as it is driven by an XML document and there's a tool that
emits a header file for you to include.
It only supports toggling features at compile time, and the feature flag
evaluators are intended to be fully constant expressions.
Features are added to `src\features.xml` and marked with a "stage". For
now, the only stages available are `AlwaysDisabled` and `AlwaysEnabled`.
Features can be toggled to different states using branch and branding
tokens, as documented in the included feature flag docs.
For a given feature Feature_XYZ, we will emit two fixtures visible to
the compiler:
1. A preprocessor define `TIL_FEATURE_XYZ_ENABLED` (usable from MIDL,
C++ and C)
2. A feature class type `Feature_XYZ` with a static constexpr member
`IsEnabled()` (usable from C++, designed for `if constexpr()`).
Like Velocity, we rely on the compiler to eliminate dead code caused by
things that compile down to `if constexpr (false)`. :)
Michael suggested that we could use `WindowsInbox` as a branding to
determine when we were being built inside Windows to supplant our use of
the `__INSIDE_WINDOWS` preprocessor token. It was brilliant.
Design Decisions
----------------
* Emitting the header as part of an MSBuild project
* WHY: This allows the MSBuild engine to ensure that the build is
only run once, even in a parallel build situation.
* Only having one feature flag document for the entire project
* WHY: Ease.
* Forcibly including `TilFeatureStaging` with `/FI` for all CL compiler
invocations.
* WHY: If this is a project-wide feature system, we should make it as
easy as possible to use.
* Emitting preprocessor definitions instead of constexpr/consteval
* WHY: Removing entire functions/includes is impossible with `if
constexpr`.
* WHY: MIDL cannot use a `static constexpr bool`, but it can rely on
the C preprocessor to remove text.
* Using MSBuild to emit the text instead of PowerShell
* WHY: This allows us to leverage MSBuild's `WriteOnlyWhenDifferent`
task parameter to avoid changing the file's modification time when
it would have resulted in the same contents. This lets us use the
same FeatureStaging header across multiple builds and multiple
branches and brandings _assuming that they do not result in a
feature flag change_.
* The risk in using a force-include is always that it, for some
reason, determines that the entire project is out of date. We've
gone to great lengths to make sure that it only does so if the
features _actually materially changed_.
2021-06-11 01:09:52 +02:00
|
|
|
<?xml version="1.0"?>
|
|
|
|
<featureStaging xmlns="http://microsoft.com/TilFeatureStaging-Schema.xsd">
|
|
|
|
<!-- See doc/feature_flags.md for more info. -->
|
|
|
|
<feature>
|
2021-06-11 01:48:54 +02:00
|
|
|
<name>Feature_ReceiveIncomingHandoff</name>
|
|
|
|
<description>OpenConsole should be able to receive incoming connections</description>
|
Add support for branch- and branding-based feature flagging (#10361)
This pull request implements a "feature flagging" system that will let
us turn Terminal and conhost features on/off by branch, "release" status
or branding (Dev, Preview, etc.).
It's loosely modelled after the Windows OS concept of "Velocity," but
only insofar as it is driven by an XML document and there's a tool that
emits a header file for you to include.
It only supports toggling features at compile time, and the feature flag
evaluators are intended to be fully constant expressions.
Features are added to `src\features.xml` and marked with a "stage". For
now, the only stages available are `AlwaysDisabled` and `AlwaysEnabled`.
Features can be toggled to different states using branch and branding
tokens, as documented in the included feature flag docs.
For a given feature Feature_XYZ, we will emit two fixtures visible to
the compiler:
1. A preprocessor define `TIL_FEATURE_XYZ_ENABLED` (usable from MIDL,
C++ and C)
2. A feature class type `Feature_XYZ` with a static constexpr member
`IsEnabled()` (usable from C++, designed for `if constexpr()`).
Like Velocity, we rely on the compiler to eliminate dead code caused by
things that compile down to `if constexpr (false)`. :)
Michael suggested that we could use `WindowsInbox` as a branding to
determine when we were being built inside Windows to supplant our use of
the `__INSIDE_WINDOWS` preprocessor token. It was brilliant.
Design Decisions
----------------
* Emitting the header as part of an MSBuild project
* WHY: This allows the MSBuild engine to ensure that the build is
only run once, even in a parallel build situation.
* Only having one feature flag document for the entire project
* WHY: Ease.
* Forcibly including `TilFeatureStaging` with `/FI` for all CL compiler
invocations.
* WHY: If this is a project-wide feature system, we should make it as
easy as possible to use.
* Emitting preprocessor definitions instead of constexpr/consteval
* WHY: Removing entire functions/includes is impossible with `if
constexpr`.
* WHY: MIDL cannot use a `static constexpr bool`, but it can rely on
the C preprocessor to remove text.
* Using MSBuild to emit the text instead of PowerShell
* WHY: This allows us to leverage MSBuild's `WriteOnlyWhenDifferent`
task parameter to avoid changing the file's modification time when
it would have resulted in the same contents. This lets us use the
same FeatureStaging header across multiple builds and multiple
branches and brandings _assuming that they do not result in a
feature flag change_.
* The risk in using a force-include is always that it, for some
reason, determines that the entire project is out of date. We've
gone to great lengths to make sure that it only does so if the
features _actually materially changed_.
2021-06-11 01:09:52 +02:00
|
|
|
<stage>AlwaysEnabled</stage>
|
|
|
|
<alwaysDisabledBrandingTokens>
|
|
|
|
<brandingToken>WindowsInbox</brandingToken>
|
|
|
|
</alwaysDisabledBrandingTokens>
|
|
|
|
</feature>
|
2021-06-11 01:48:54 +02:00
|
|
|
|
2021-07-08 22:55:31 +02:00
|
|
|
<feature>
|
|
|
|
<name>Feature_EditableActionsPage</name>
|
|
|
|
<description>The Actions page in the settings UI should allow users to edit actions.</description>
|
|
|
|
<stage>AlwaysEnabled</stage>
|
|
|
|
<alwaysDisabledReleaseTokens/>
|
|
|
|
</feature>
|
|
|
|
|
2021-07-14 01:33:22 +02:00
|
|
|
<feature>
|
|
|
|
<name>Feature_EditableUnfocusedAppearance</name>
|
|
|
|
<description>The unfocused appearance section in profiles in the SUI that allows users to create and edit unfocused appearances.</description>
|
|
|
|
<stage>AlwaysEnabled</stage>
|
|
|
|
<alwaysDisabledReleaseTokens/>
|
|
|
|
</feature>
|
|
|
|
|
2021-06-11 01:48:54 +02:00
|
|
|
<feature>
|
|
|
|
<name>Feature_AttemptHandoff</name>
|
|
|
|
<description>conhost should try to hand connections over to OpenConsole</description>
|
|
|
|
<stage>AlwaysDisabled</stage>
|
|
|
|
<alwaysEnabledBrandingTokens>
|
|
|
|
<brandingToken>WindowsInbox</brandingToken>
|
|
|
|
</alwaysEnabledBrandingTokens>
|
|
|
|
</feature>
|
|
|
|
|
|
|
|
<feature>
|
|
|
|
<name>Feature_ConhostDxEngine</name>
|
|
|
|
<description>Controls whether conhost supports the DX engine and the UseDx registry key</description>
|
|
|
|
<stage>AlwaysEnabled</stage>
|
|
|
|
<alwaysDisabledBrandingTokens>
|
|
|
|
<brandingToken>WindowsInbox</brandingToken>
|
|
|
|
</alwaysDisabledBrandingTokens>
|
|
|
|
</feature>
|
|
|
|
<feature>
|
|
|
|
<name>Feature_DxEngineShaderSupport</name>
|
|
|
|
<description>Controls whether the DX engine is built with shader support.</description>
|
|
|
|
<stage>AlwaysEnabled</stage>
|
|
|
|
<alwaysDisabledBrandingTokens>
|
|
|
|
<brandingToken>WindowsInbox</brandingToken>
|
|
|
|
</alwaysDisabledBrandingTokens>
|
|
|
|
</feature>
|
|
|
|
|
|
|
|
<feature>
|
|
|
|
<name>Feature_UseNumpadEventsForClipboardInput</name>
|
|
|
|
<description>Controls whether the clipboard converter (and ConPTY InputStateMachine) uses Numpad events instead of UChar</description>
|
|
|
|
<stage>AlwaysDisabled</stage>
|
|
|
|
<alwaysEnabledBrandingTokens>
|
|
|
|
<!--
|
|
|
|
To reduce the risk of compatibility issues inside Windows, we're going to continue using the old
|
|
|
|
version of GetQuickCharWidth to determine whether a character should be synthesized into numpad
|
|
|
|
events.
|
|
|
|
-->
|
|
|
|
<brandingToken>WindowsInbox</brandingToken>
|
|
|
|
</alwaysEnabledBrandingTokens>
|
|
|
|
</feature>
|
Reintroduce the Defaults page and the Reset buttons (#10588)
This pull request brings back the "Base Layer" page, now renamed to
"Defaults", and the "Reset to inherited value" buttons. The scope of
inheritance for which buttons will display has been widened.
The button will be visible in the following cases:
The user has set a setting for the current profile, and it overrides...
1. ... something in profiles.defaults.
2. ... something in a Fragment Extension profile.
3. ... something from a Dynamic Profile Generator.
4. ... something from the compiled-in defaults.
Compared to the original implementation of reset arrows, cases (1), (3)
and (4) are new. Rationale:
(1) The user can see a setting on the Defaults page, and they need a way
to reset back to it.
(3) Dynamic profiles are not meaningfully different from fragments, and
users may need a way to reset back to the default value generated
for WSL or PowerShell.
(4) The user can see a setting on the Defaults page, **BUT** they are
not the one who created it. They *still* need a way to get back to
it.
To support this, I've introduced another origin tag, "User", and renamed
"Custom" to "None". Due to the way origin/override detection works¹, we
cannot otherwise disambiguate between settings that came from the user
and settings that came from the compiled-in defaults.
Changes were required in TerminalSettings such that we could construct a
settings object with a profile that does not have a GUID. In making this
change, I fixed a bit of silliness where we took a profile, extracted
its guid, and used that guid to look up the same profile object. Oops.
I also fixed the PropertyChanged notifier to include the
XxxOverrideSource property.
The presence of the page and the reset arrows is restricted to
Preview- or Dev-branded builds. Stable builds will retain their current
behavior.
¹ `XxxOverrideSource` returns the profile *above* the current profile
that holds a value for setting `Xxx`. When the value is the
compiled-in value, `XxxOverrideSource` will be `null`. Since it's
supposed to be the profile above the current profile, it will also be
`null` if the profile contains a setting at this layer.
In short, `null` means "user specified" *or* "compiled in". Oops.
Fixes #10430
Validation
----------
* [x] Tested Release build to make sure it's mostly arrow-free (apart from fragments)
2021-07-10 00:03:41 +02:00
|
|
|
|
2021-08-12 21:54:39 +02:00
|
|
|
<feature>
|
|
|
|
<name>Feature_TrayIcon</name>
|
|
|
|
<description>Controls whether the Tray Icon and related settings (aka. MinimizeToTray and AlwaysShowTrayIcon) are enabled</description>
|
|
|
|
<stage>AlwaysEnabled</stage>
|
|
|
|
<alwaysDisabledReleaseTokens/>
|
|
|
|
</feature>
|
|
|
|
|
Reintroduce the Defaults page and the Reset buttons (#10588)
This pull request brings back the "Base Layer" page, now renamed to
"Defaults", and the "Reset to inherited value" buttons. The scope of
inheritance for which buttons will display has been widened.
The button will be visible in the following cases:
The user has set a setting for the current profile, and it overrides...
1. ... something in profiles.defaults.
2. ... something in a Fragment Extension profile.
3. ... something from a Dynamic Profile Generator.
4. ... something from the compiled-in defaults.
Compared to the original implementation of reset arrows, cases (1), (3)
and (4) are new. Rationale:
(1) The user can see a setting on the Defaults page, and they need a way
to reset back to it.
(3) Dynamic profiles are not meaningfully different from fragments, and
users may need a way to reset back to the default value generated
for WSL or PowerShell.
(4) The user can see a setting on the Defaults page, **BUT** they are
not the one who created it. They *still* need a way to get back to
it.
To support this, I've introduced another origin tag, "User", and renamed
"Custom" to "None". Due to the way origin/override detection works¹, we
cannot otherwise disambiguate between settings that came from the user
and settings that came from the compiled-in defaults.
Changes were required in TerminalSettings such that we could construct a
settings object with a profile that does not have a GUID. In making this
change, I fixed a bit of silliness where we took a profile, extracted
its guid, and used that guid to look up the same profile object. Oops.
I also fixed the PropertyChanged notifier to include the
XxxOverrideSource property.
The presence of the page and the reset arrows is restricted to
Preview- or Dev-branded builds. Stable builds will retain their current
behavior.
¹ `XxxOverrideSource` returns the profile *above* the current profile
that holds a value for setting `Xxx`. When the value is the
compiled-in value, `XxxOverrideSource` will be `null`. Since it's
supposed to be the profile above the current profile, it will also be
`null` if the profile contains a setting at this layer.
In short, `null` means "user specified" *or* "compiled in". Oops.
Fixes #10430
Validation
----------
* [x] Tested Release build to make sure it's mostly arrow-free (apart from fragments)
2021-07-10 00:03:41 +02:00
|
|
|
<feature>
|
|
|
|
<name>Feature_ShowProfileDefaultsInSettings</name>
|
|
|
|
<description>Whether to show the "defaults" page in the Terminal settings UI</description>
|
|
|
|
<id>10430</id>
|
|
|
|
<stage>AlwaysEnabled</stage>
|
|
|
|
<!-- This feature will not ship to Stable until it is complete. -->
|
|
|
|
<alwaysDisabledReleaseTokens />
|
|
|
|
</feature>
|
Persist window layout on window close (#10972)
This commit adds initial support for saving window layout on application
close.
Done:
- Add user setting for if tabs should be maintained.
- Added events to track the number of open windows for the monarch, and
then save if you are the last window closing.
- Saves layout when the user explicitly hits the "Close Window" button.
- If the user manually closed all of their tabs (through the tab x
button or through closing all panes on the tab) then remove any saved
state.
- Saves in the ApplicationState file a list of actions the terminal can
perform to restore its layout and the window size/position
information.
- This saves an action to focus the correct pane, but this won't
actually work without #10978. Note that if you have a pane zoomed, it
does still zoom the correct pane, but when you unzoom it will have a
different pane selected.
Todo:
- multiple windows? Right now it can only handle loading/saving one
window.
- PR #11083 will save multiple windows.
- This also sometimes runs into the existing bug where multiple tabs
appear to be focused on opening.
Next Steps:
- The business logic of when the save is triggered can be adjusted as
necessary.
- Right now I am taking the pragmatic approach and just saving the state
as an array of objects, but only ever populate it with 1, that way
saving multiple windows in the future could be added without breaking
schema compatibility. Selfishly I'm hoping that handling multiple
windows could be spun off into another pr/feature for now.
- One possible thing that can maybe be done is that the commandline can
be augmented with a "--saved ##" attribute that would load from the
nth saved state if it exists. e.g. if there are 3 saved windows, on
first load it can spawn three wt --saved {0,1,2} that would reopen the
windows? This way there also exists a way to load a copy of a previous
window (if it is in the saved state).
- Is the application state something that is planned to be public/user
editable? In theory the user could since it is just json, but I don't
know what it buys them over just modifying their settings and
startupActions.
Validation Steps Performed:
- The happy path: open terminal -> set setting to true -> close terminal
-> reopen and see tabs. Tested with powershell/cmd/wsl windows.
- That closing all panes/tabs on their own will remove the saved
session.
- Open multiple windows, close windows and confirm that the last window
closed saves its state.
The generated file stores a sequence of actions that will be executed to
restore the terminal to its saved form.
References #8324
This is also one of the items on microsoft/terminal#5000
Closes #766
2021-09-09 00:44:53 +02:00
|
|
|
|
|
|
|
<feature>
|
|
|
|
<name>Feature_PersistedWindowLayout</name>
|
|
|
|
<description>Whether to allow the user to enable persisted window layout saving and loading</description>
|
|
|
|
<id>766</id>
|
|
|
|
<stage>AlwaysEnabled</stage>
|
|
|
|
<!-- This feature will not ship to Stable until it is complete. -->
|
|
|
|
<alwaysDisabledReleaseTokens />
|
|
|
|
</feature>
|
Add support for branch- and branding-based feature flagging (#10361)
This pull request implements a "feature flagging" system that will let
us turn Terminal and conhost features on/off by branch, "release" status
or branding (Dev, Preview, etc.).
It's loosely modelled after the Windows OS concept of "Velocity," but
only insofar as it is driven by an XML document and there's a tool that
emits a header file for you to include.
It only supports toggling features at compile time, and the feature flag
evaluators are intended to be fully constant expressions.
Features are added to `src\features.xml` and marked with a "stage". For
now, the only stages available are `AlwaysDisabled` and `AlwaysEnabled`.
Features can be toggled to different states using branch and branding
tokens, as documented in the included feature flag docs.
For a given feature Feature_XYZ, we will emit two fixtures visible to
the compiler:
1. A preprocessor define `TIL_FEATURE_XYZ_ENABLED` (usable from MIDL,
C++ and C)
2. A feature class type `Feature_XYZ` with a static constexpr member
`IsEnabled()` (usable from C++, designed for `if constexpr()`).
Like Velocity, we rely on the compiler to eliminate dead code caused by
things that compile down to `if constexpr (false)`. :)
Michael suggested that we could use `WindowsInbox` as a branding to
determine when we were being built inside Windows to supplant our use of
the `__INSIDE_WINDOWS` preprocessor token. It was brilliant.
Design Decisions
----------------
* Emitting the header as part of an MSBuild project
* WHY: This allows the MSBuild engine to ensure that the build is
only run once, even in a parallel build situation.
* Only having one feature flag document for the entire project
* WHY: Ease.
* Forcibly including `TilFeatureStaging` with `/FI` for all CL compiler
invocations.
* WHY: If this is a project-wide feature system, we should make it as
easy as possible to use.
* Emitting preprocessor definitions instead of constexpr/consteval
* WHY: Removing entire functions/includes is impossible with `if
constexpr`.
* WHY: MIDL cannot use a `static constexpr bool`, but it can rely on
the C preprocessor to remove text.
* Using MSBuild to emit the text instead of PowerShell
* WHY: This allows us to leverage MSBuild's `WriteOnlyWhenDifferent`
task parameter to avoid changing the file's modification time when
it would have resulted in the same contents. This lets us use the
same FeatureStaging header across multiple builds and multiple
branches and brandings _assuming that they do not result in a
feature flag change_.
* The risk in using a force-include is always that it, for some
reason, determines that the entire project is out of date. We've
gone to great lengths to make sure that it only does so if the
features _actually materially changed_.
2021-06-11 01:09:52 +02:00
|
|
|
</featureStaging>
|