Skip to content

Commit

Permalink
Add support for setting tabColor on the command line (#8102)
Browse files Browse the repository at this point in the history
* Add a tabColor parameter to the `new-tab` and `split-panes` command
* Add --tabColor to the command line, to allow bootstrapping with tabs
  of different colors

Add another field to NewTerminalArgs. Use this field to set
StartingTabColor in Terminal. This color gets overridden by the color
defined by the profile / VT, however can be overridden with the color
picker.

Since the color is the property of the Terminal, when defined for the
tab this color is associated only with the first pane/terminal of the
tab. Additional panes will not inherit this color (to prevent advanced
resolution, where we need to resolve between the inherited color and the
one specified for the pane).

## Validation Steps Performed
* UT for parameters parsing
* Running system with several tabs of different colors.
* Adding custom actions with colors
* Performing operations like split pane, duplicate and so on

Closes #8075
  • Loading branch information
Don-Vito committed Nov 20, 2020
1 parent a52a1d3 commit fd37e1d
Show file tree
Hide file tree
Showing 16 changed files with 146 additions and 43 deletions.
5 changes: 5 additions & 0 deletions doc/cascadia/profiles.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,11 @@
"index": {
"type": "integer",
"description": "The index of the profile in the new tab dropdown (starting at 0)"
},
"tabColor": {
"$ref": "#/definitions/Color",
"default": null,
"description": "If provided, will set the tab's color to the given value"
}
},
"type": "object"
Expand Down
2 changes: 1 addition & 1 deletion src/cascadia/LocalTests_SettingsModel/KeyBindingsTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,7 @@ namespace SettingsModelLocalTests
// Verify the args have the expected value
VERIFY_IS_NOT_NULL(realArgs.TabColor());
// Remember that COLORREFs are actually BBGGRR order, while the string is in #RRGGBB order
VERIFY_ARE_EQUAL(static_cast<uint32_t>(til::color(0x563412)), realArgs.TabColor().Value());
VERIFY_ARE_EQUAL(til::color(0x563412), til::color(realArgs.TabColor().Value()));
}
{
KeyChord kc{ true, false, false, static_cast<int32_t>('F') };
Expand Down
98 changes: 73 additions & 25 deletions src/cascadia/LocalTests_TerminalApp/CommandlineTest.cpp

Large diffs are not rendered by default.

11 changes: 4 additions & 7 deletions src/cascadia/TerminalApp/AppActionHandlers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -350,23 +350,20 @@ namespace winrt::TerminalApp::implementation
void TerminalPage::_HandleSetTabColor(const IInspectable& /*sender*/,
const ActionEventArgs& args)
{
std::optional<til::color> tabColor;
Windows::Foundation::IReference<Windows::UI::Color> tabColor;

if (const auto& realArgs = args.ActionArgs().try_as<SetTabColorArgs>())
{
if (realArgs.TabColor() != nullptr)
{
tabColor = realArgs.TabColor().Value();
}
tabColor = realArgs.TabColor();
}

if (auto focusedTab = _GetFocusedTab())
{
if (auto activeTab = _GetTerminalTabImpl(focusedTab))
{
if (tabColor.has_value())
if (tabColor)
{
activeTab->SetRuntimeTabColor(tabColor.value());
activeTab->SetRuntimeTabColor(tabColor.Value());
}
else
{
Expand Down
12 changes: 12 additions & 0 deletions src/cascadia/TerminalApp/AppCommandlineArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "pch.h"
#include "AppLogic.h"
#include "AppCommandlineArgs.h"
#include "../types/inc/utils.hpp"
#include <LibraryResources.h>

using namespace winrt::TerminalApp;
Expand Down Expand Up @@ -355,6 +356,10 @@ void AppCommandlineArgs::_addNewTerminalArgs(AppCommandlineArgs::NewTerminalSubc
_startingTitle,
RS_A(L"CmdTitleArgDesc"));

subcommand.tabColorOption = subcommand.subcommand->add_option("--tabColor",
_startingTabColor,
RS_A(L"CmdTabColorArgDesc"));

// Using positionals_at_end allows us to support "wt new-tab -d wsl -d Ubuntu"
// without CLI11 thinking that we've specified -d twice.
// There's an alternate construction where we make all subcommands "prefix commands",
Expand Down Expand Up @@ -416,6 +421,12 @@ NewTerminalArgs AppCommandlineArgs::_getNewTerminalArgs(AppCommandlineArgs::NewT
args.TabTitle(winrt::to_hstring(_startingTitle));
}

if (*subcommand.tabColorOption)
{
const auto tabColor = Microsoft::Console::Utils::ColorFromHexString(_startingTabColor);
args.TabColor(static_cast<winrt::Windows::UI::Color>(tabColor));
}

return args;
}

Expand Down Expand Up @@ -450,6 +461,7 @@ void AppCommandlineArgs::_resetStateToDefault()
_profileName.clear();
_startingDirectory.clear();
_startingTitle.clear();
_startingTabColor.clear();
_commandline.clear();

_splitVertical = false;
Expand Down
2 changes: 2 additions & 0 deletions src/cascadia/TerminalApp/AppCommandlineArgs.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class TerminalApp::AppCommandlineArgs final
CLI::Option* profileNameOption;
CLI::Option* startingDirectoryOption;
CLI::Option* titleOption;
CLI::Option* tabColorOption;
};

struct NewPaneSubcommand : public NewTerminalSubcommand
Expand All @@ -74,6 +75,7 @@ class TerminalApp::AppCommandlineArgs final
std::string _profileName;
std::string _startingDirectory;
std::string _startingTitle;
std::string _startingTabColor;

// _commandline will contain the command line with which we'll be spawning a new terminal
std::vector<std::string> _commandline;
Expand Down
3 changes: 3 additions & 0 deletions src/cascadia/TerminalApp/Resources/en-US/Resources.resw
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,9 @@
<value>Open the terminal with the provided title instead of the profile's set "title"</value>
<comment>{Locked="\"title\""}</comment>
</data>
<data name="CmdTabColorArgDesc" xml:space="preserve">
<value>Open the tab with the specified color, in #rrggbb format</value>
</data>
<data name="CmdVersionDesc" xml:space="preserve">
<value>Display the application version</value>
</data>
Expand Down
4 changes: 4 additions & 0 deletions src/cascadia/TerminalApp/TerminalSettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ namespace winrt::TerminalApp::implementation
{
settings.StartingTitle(newTerminalArgs.TabTitle());
}
if (newTerminalArgs.TabColor())
{
settings.StartingTabColor(static_cast<uint32_t>(til::color(newTerminalArgs.TabColor().Value())));
}
}

return { profileGuid, settings };
Expand Down
10 changes: 10 additions & 0 deletions src/cascadia/TerminalApp/TerminalSettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,16 @@ namespace winrt::TerminalApp::implementation

GETSET_PROPERTY(Windows::Foundation::IReference<uint32_t>, TabColor, nullptr);

// When set, StartingTabColor allows to create a terminal with a "sticky" tab color.
// This color is prioritized above the TabColor (that is usually initialized based on profile settings).
// Due to this prioritization, the tab color will be preserved upon settings reload
// (even if the profile's tab color gets altered or removed).
// This property is expected to be passed only once upon terminal creation.
// TODO: to ensure that this property is not populated during settings reload,
// we should consider moving this property to a separate interface,
// passed to the terminal only upon creation.
GETSET_PROPERTY(Windows::Foundation::IReference<uint32_t>, StartingTabColor, nullptr);

// ------------------------ End of Core Settings -----------------------

GETSET_PROPERTY(hstring, ProfileName);
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalCore/ICoreSettings.idl
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ namespace Microsoft.Terminal.TerminalControl
Boolean ForceVTInput;

Windows.Foundation.IReference<UInt32> TabColor;
Windows.Foundation.IReference<UInt32> StartingTabColor;
};

}
13 changes: 11 additions & 2 deletions src/cascadia/TerminalCore/Terminal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,9 +166,15 @@ void Terminal::UpdateSettings(ICoreSettings settings)
{
_tabColor = til::color(settings.TabColor().Value() | 0xff000000);
}

if (!_startingTabColor && settings.StartingTabColor())
{
_startingTabColor = til::color(settings.StartingTabColor().Value() | 0xff000000);
}

if (_pfnTabColorChanged)
{
_pfnTabColorChanged(_tabColor);
_pfnTabColorChanged(GetTabColor());
}

// TODO:MSFT:21327402 - if HistorySize has changed, resize the buffer so we
Expand Down Expand Up @@ -1171,9 +1177,12 @@ void Terminal::ClearPatternTree() noexcept
_InvalidatePatternTree(oldTree);
}

// Method Description:
// - Returns the tab color
// If the starting color exits, it's value is preferred
const std::optional<til::color> Terminal::GetTabColor() const noexcept
{
return _tabColor;
return _startingTabColor.has_value() ? _startingTabColor : _tabColor;
}

BlinkingState& Terminal::GetBlinkingState() const noexcept
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalCore/Terminal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ class Microsoft::Terminal::Core::Terminal final :
std::optional<std::wstring> _title;
std::wstring _startingTitle;
std::optional<til::color> _tabColor;
std::optional<til::color> _startingTabColor;

std::array<COLORREF, XTERM_COLOR_TABLE_SIZE> _colorTable;
COLORREF _defaultFg;
Expand Down
11 changes: 9 additions & 2 deletions src/cascadia/TerminalSettingsModel/ActionArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,13 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
{
ss << fmt::format(L"title: {}, ", _TabTitle);
}

if (_TabColor)
{
const til::color tabColor{ _TabColor.Value() };
ss << fmt::format(L"tabColor: {}, ", tabColor.ToHexString(true));
}

auto s = ss.str();
if (s.empty())
{
Expand Down Expand Up @@ -300,10 +307,10 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
// "Reset tab color"
if (_TabColor)
{
til::color c{ _TabColor.Value() };
til::color tabColor{ _TabColor.Value() };
return winrt::hstring{
fmt::format(std::wstring_view(RS_(L"SetTabColorCommandKey")),
c.ToHexString(true))
tabColor.ToHexString(true))
};
}

Expand Down
12 changes: 7 additions & 5 deletions src/cascadia/TerminalSettingsModel/ActionArgs.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,14 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
GETSET_PROPERTY(winrt::hstring, Commandline, L"");
GETSET_PROPERTY(winrt::hstring, StartingDirectory, L"");
GETSET_PROPERTY(winrt::hstring, TabTitle, L"");
GETSET_PROPERTY(Windows::Foundation::IReference<Windows::UI::Color>, TabColor, nullptr);
GETSET_PROPERTY(Windows::Foundation::IReference<int32_t>, ProfileIndex, nullptr);
GETSET_PROPERTY(winrt::hstring, Profile, L"");

static constexpr std::string_view CommandlineKey{ "commandline" };
static constexpr std::string_view StartingDirectoryKey{ "startingDirectory" };
static constexpr std::string_view TabTitleKey{ "tabTitle" };
static constexpr std::string_view TabColorKey{ "tabColor" };
static constexpr std::string_view ProfileIndexKey{ "index" };
static constexpr std::string_view ProfileKey{ "profile" };

Expand All @@ -77,6 +79,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
return other.Commandline() == _Commandline &&
other.StartingDirectory() == _StartingDirectory &&
other.TabTitle() == _TabTitle &&
other.TabColor() == _TabColor &&
other.ProfileIndex() == _ProfileIndex &&
other.Profile() == _Profile;
};
Expand All @@ -89,6 +92,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
JsonUtils::GetValueForKey(json, TabTitleKey, args->_TabTitle);
JsonUtils::GetValueForKey(json, ProfileIndexKey, args->_ProfileIndex);
JsonUtils::GetValueForKey(json, ProfileKey, args->_Profile);
JsonUtils::GetValueForKey(json, TabColorKey, args->_TabColor);
return *args;
}
Model::NewTerminalArgs Copy() const
Expand All @@ -97,6 +101,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
copy->_Commandline = _Commandline;
copy->_StartingDirectory = _StartingDirectory;
copy->_TabTitle = _TabTitle;
copy->_TabColor = _TabColor;
copy->_ProfileIndex = _ProfileIndex;
copy->_Profile = _Profile;
return *copy;
Expand Down Expand Up @@ -493,7 +498,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
struct SetTabColorArgs : public SetTabColorArgsT<SetTabColorArgs>
{
SetTabColorArgs() = default;
GETSET_PROPERTY(Windows::Foundation::IReference<uint32_t>, TabColor, nullptr);
GETSET_PROPERTY(Windows::Foundation::IReference<Windows::UI::Color>, TabColor, nullptr);

static constexpr std::string_view ColorKey{ "color" };

Expand All @@ -513,10 +518,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
{
// LOAD BEARING: Not using make_self here _will_ break you in the future!
auto args = winrt::make_self<SetTabColorArgs>();
if (const auto temp{ JsonUtils::GetValueForKey<std::optional<til::color>>(json, ColorKey) })
{
args->_TabColor = static_cast<uint32_t>(*temp);
}
JsonUtils::GetValueForKey(json, ColorKey, args->_TabColor);
return { *args, {} };
}
IActionArgs Copy() const
Expand Down
3 changes: 2 additions & 1 deletion src/cascadia/TerminalSettingsModel/ActionArgs.idl
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ namespace Microsoft.Terminal.Settings.Model
String Commandline;
String StartingDirectory;
String TabTitle;
Windows.Foundation.IReference<Windows.UI.Color> TabColor;
String Profile; // Either a GUID or a profile's name if the GUID isn't a match
// ProfileIndex can be null (for "use the default"), so this needs to be
// a IReference, so it's nullable
Expand Down Expand Up @@ -130,7 +131,7 @@ namespace Microsoft.Terminal.Settings.Model

[default_interface] runtimeclass SetTabColorArgs : IActionArgs
{
Windows.Foundation.IReference<UInt32> TabColor { get; };
Windows.Foundation.IReference<Windows.UI.Color> TabColor { get; };
};

[default_interface] runtimeclass RenameTabArgs : IActionArgs
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/UnitTests_TerminalCore/MockTermSettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ namespace TerminalCoreUnitTests
void ForceVTInput(bool) {}

GETSET_PROPERTY(winrt::Windows::Foundation::IReference<uint32_t>, TabColor, nullptr);
GETSET_PROPERTY(winrt::Windows::Foundation::IReference<uint32_t>, StartingTabColor, nullptr);

private:
int32_t _historySize;
Expand Down

0 comments on commit fd37e1d

Please sign in to comment.