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

Implement cell size customizations #14255

Merged
merged 8 commits into from
Feb 14, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions doc/cascadia/profiles.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,13 @@
},
"type": "object"
},
"CSSLengthPercentage": {
"pattern": "^[+-]?\\d+(?:\\.\\d+)?(?:%|ch|pt|px)?$",
"type": [
"string",
"null"
]
},
"ProfileGuid": {
"default": "{}",
"pattern": "^\\{[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}\\}$",
Expand Down Expand Up @@ -2086,6 +2093,19 @@
"null"
]
},
"cellSize": {
"type": "object",
"properties": {
"height": {
"$ref": "#/$defs/CSSLengthPercentage",
"description": "Override the height of the terminal's cells. The override works similar to CSS' line-height. Defaults to the sum of the natural glyph ascend, descend and line-gap of the primary font rounded to the nearest pixel. The default is usually quite close to setting this to 1.2."
},
"width": {
"$ref": "#/$defs/CSSLengthPercentage",
"description": "Override the width of the terminal's cells. The override works similar to CSS' line-height. Defaults to the natural glyph advance width of the primary font rounded to the nearest pixel."
}
}
},
"backgroundImage": {
"description": "Sets the file location of the image to draw over the window background.",
"oneOf": [
Expand Down
4 changes: 4 additions & 0 deletions src/cascadia/TerminalControl/ControlCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -713,6 +713,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation

auto lock = _terminal->LockForWriting();

_cellSizeX = CSSLengthPercentage::FromString(_settings->CellSizeX().c_str());
_cellSizeY = CSSLengthPercentage::FromString(_settings->CellSizeY().c_str());
_runtimeOpacity = std::nullopt;
_runtimeUseAcrylic = std::nullopt;

Expand Down Expand Up @@ -871,6 +873,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_actualFont = { fontFace, 0, fontWeight.Weight, _desiredFont.GetEngineSize(), CP_UTF8, false };
_actualFontFaceName = { fontFace };

_desiredFont.SetCellSizes(_cellSizeX, _cellSizeY);

const auto before = _actualFont.GetSize();
_updateFont();
const auto after = _actualFont.GetSize();
Expand Down
2 changes: 2 additions & 0 deletions src/cascadia/TerminalControl/ControlCore.h
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
FontInfoDesired _desiredFont;
FontInfo _actualFont;
winrt::hstring _actualFontFaceName;
CSSLengthPercentage _cellSizeX;
CSSLengthPercentage _cellSizeY;

// storage location for the leading surrogate of a utf-16 surrogate pair
std::optional<wchar_t> _leadingSurrogate{ std::nullopt };
Expand Down
2 changes: 2 additions & 0 deletions src/cascadia/TerminalControl/IControlSettings.idl
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ namespace Microsoft.Terminal.Control
String Padding { get; };
Windows.Foundation.Collections.IMap<String, UInt32> FontFeatures { get; };
Windows.Foundation.Collections.IMap<String, Single> FontAxes { get; };
String CellSizeX { get; };
String CellSizeY { get; };

Microsoft.Terminal.Control.IKeyBindings KeyBindings { get; };

Expand Down
104 changes: 100 additions & 4 deletions src/cascadia/TerminalSettingsEditor/Appearances.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,88 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
}
}

double AppearanceViewModel::LineHeight() const noexcept
{
const auto cellSizeY = _appearance.SourceProfile().CellSizeY();
const auto str = cellSizeY.c_str();

auto& errnoRef = errno; // Nonzero cost, pay it once.
errnoRef = 0;

wchar_t* end;
const auto value = std::wcstod(str, &end);

return str == end || errnoRef == ERANGE ? NAN : value;
}

void AppearanceViewModel::LineHeight(const double value)
{
wchar_t buffer[16];
std::wstring_view view;

if (value >= 0.1 && value <= 10.0)
{
auto length = gsl::narrow<size_t>(swprintf_s(&buffer[0], std::size(buffer), L"%.6f", value));
const auto separator = std::wstring_view{ &buffer[0], length }.find(L'.');

if (separator != std::wstring_view::npos)
{
for (; length > separator && buffer[length - 1] == L'0'; --length)
{
}
// winrt::hstring expects a null-terminated string
buffer[length] = L'\0';
}

view = { &buffer[0], length };
}

const auto profile = _appearance.SourceProfile();

if (profile.CellSizeY() != view)
{
if (view.empty())
{
profile.ClearCellSizeY();
}
lhecker marked this conversation as resolved.
Show resolved Hide resolved
else
{
profile.CellSizeY(view);
}
_NotifyChanges(L"HasLineHeight", L"LineHeight");
}
}

bool AppearanceViewModel::HasLineHeight()
{
return _appearance.SourceProfile().HasCellSizeY();
}

void AppearanceViewModel::ClearLineHeight()
{
LineHeight({});
}

Model::Profile AppearanceViewModel::LineHeightOverrideSource()
{
return _appearance.SourceProfile().CellSizeYOverrideSource();
}

void AppearanceViewModel::SetFontWeightFromDouble(double fontWeight)
{
FontWeight(Converters::DoubleToFontWeight(fontWeight));
}

void AppearanceViewModel::SetBackgroundImageOpacityFromPercentageValue(double percentageValue)
{
BackgroundImageOpacity(Converters::PercentageValueToPercentage(percentageValue));
}

void AppearanceViewModel::SetBackgroundImagePath(winrt::hstring path)
{
BackgroundImagePath(path);
}

bool AppearanceViewModel::UseDesktopBGImage()
{
return BackgroundImagePath() == L"desktopWallpaper";
Expand Down Expand Up @@ -83,6 +165,16 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
return BackgroundImagePath() != L"";
}

IMapView<hstring, Model::ColorScheme> AppearanceViewModel::Schemes()
{
return _Schemes;
}

void AppearanceViewModel::Schemes(const IMapView<hstring, Model::ColorScheme>& val)
{
_Schemes = val;
}

DependencyProperty Appearances::_AppearanceProperty{ nullptr };

Appearances::Appearances() :
Expand All @@ -96,10 +188,14 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
// > .NET rounds to 12 significant digits when displaying doubles, so we will [...]
// ...obviously not do that, because this is an UI element for humans. This prevents
// issues when displaying 32-bit floats, because WinUI is unaware about their existence.
SignificantDigitsNumberRounder rounder;
rounder.SignificantDigits(6);
// BODGY: Depends on WinUI internals.
_fontSizeBox().NumberFormatter().as<DecimalFormatter>().NumberRounder(rounder);
IncrementNumberRounder rounder;
rounder.Increment(1e-6);
Comment on lines +198 to +199
Copy link
Member Author

@lhecker lhecker Oct 19, 2022

Choose a reason for hiding this comment

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


for (const auto& box : { _fontSizeBox(), _lineHeightBox() })
{
// BODGY: Depends on WinUI internals.
box.NumberFormatter().as<DecimalFormatter>().NumberRounder(rounder);
}
}

INITIALIZE_BINDABLE_ENUM_SETTING(CursorShape, CursorStyle, winrt::Microsoft::Terminal::Core::CursorStyle, L"Profile_CursorShape", L"Content");
Expand Down
25 changes: 11 additions & 14 deletions src/cascadia/TerminalSettingsEditor/Appearances.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,26 +51,22 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
public:
AppearanceViewModel(const Model::AppearanceConfig& appearance);

void SetFontWeightFromDouble(double fontWeight)
{
FontWeight(winrt::Microsoft::Terminal::Settings::Editor::Converters::DoubleToFontWeight(fontWeight));
}
void SetBackgroundImageOpacityFromPercentageValue(double percentageValue)
{
BackgroundImageOpacity(winrt::Microsoft::Terminal::Settings::Editor::Converters::PercentageValueToPercentage(percentageValue));
}
void SetBackgroundImagePath(winrt::hstring path)
{
BackgroundImagePath(path);
}
double LineHeight() const noexcept;
void LineHeight(const double value);
bool HasLineHeight();
void ClearLineHeight();
Model::Profile LineHeightOverrideSource();
void SetFontWeightFromDouble(double fontWeight);
void SetBackgroundImageOpacityFromPercentageValue(double percentageValue);
void SetBackgroundImagePath(winrt::hstring path);

// background image
bool UseDesktopBGImage();
void UseDesktopBGImage(const bool useDesktop);
bool BackgroundImageSettingsVisible();

Windows::Foundation::Collections::IMapView<hstring, Model::ColorScheme> Schemes() { return _Schemes; }
void Schemes(const Windows::Foundation::Collections::IMapView<hstring, Model::ColorScheme>& val) { _Schemes = val; }
Windows::Foundation::Collections::IMapView<hstring, Model::ColorScheme> Schemes();
void Schemes(const Windows::Foundation::Collections::IMapView<hstring, Model::ColorScheme>& val);

WINRT_PROPERTY(bool, IsDefault, false);
WINRT_PROPERTY(IHostedInWindow, WindowRoot, nullptr);
Expand Down Expand Up @@ -99,6 +95,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
Model::AppearanceConfig _appearance;
winrt::hstring _lastBgImagePath;
Windows::Foundation::Collections::IMapView<hstring, Model::ColorScheme> _Schemes;
float _cachedLineHeight = 0;
};

struct Appearances : AppearancesT<Appearances>
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalSettingsEditor/Appearances.idl
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ namespace Microsoft.Terminal.Settings.Editor

OBSERVABLE_PROJECTED_APPEARANCE_SETTING(String, FontFace);
OBSERVABLE_PROJECTED_APPEARANCE_SETTING(Single, FontSize);
OBSERVABLE_PROJECTED_APPEARANCE_SETTING(Double, LineHeight);
Copy link
Member

Choose a reason for hiding this comment

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

one's a single, one's a double!

Copy link
Member Author

Choose a reason for hiding this comment

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

Double is technically the better one, because that's what WinUI's setters and getters use. But we use float and Single throughout the project (which is alright - we don't need more than 2-3 decimal places for anything), including for the FontSize property. LineHeight on the other hand is a custom getter/setter and I felt like it'd be better to use Double if we can when interfacing with WinUI.

OBSERVABLE_PROJECTED_APPEARANCE_SETTING(Windows.UI.Text.FontWeight, FontWeight);

OBSERVABLE_PROJECTED_APPEARANCE_SETTING(String, ColorSchemeName);
Expand Down
18 changes: 18 additions & 0 deletions src/cascadia/TerminalSettingsEditor/Appearances.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,24 @@
Value="{x:Bind Appearance.FontSize, Mode=TwoWay}" />
</local:SettingContainer>

<!-- Line Height -->
<local:SettingContainer x:Uid="Profile_LineHeight"
ClearSettingValue="{x:Bind Appearance.ClearLineHeight}"
HasSettingValue="{x:Bind Appearance.HasLineHeight, Mode=OneWay}"
SettingOverrideSource="{x:Bind Appearance.LineHeightOverrideSource, Mode=OneWay}"
Visibility="{x:Bind Appearance.IsDefault, Mode=OneWay}">
<muxc:NumberBox x:Name="_lineHeightBox"
lhecker marked this conversation as resolved.
Show resolved Hide resolved
x:Uid="Profile_LineHeightBox"
AcceptsExpression="False"
lhecker marked this conversation as resolved.
Show resolved Hide resolved
LargeChange="0.1"
Maximum="10"
Minimum="0.1"
SmallChange="0.1"
SpinButtonPlacementMode="Compact"
lhecker marked this conversation as resolved.
Show resolved Hide resolved
Style="{StaticResource NumberBoxSettingStyle}"
Value="{x:Bind Appearance.LineHeight, Mode=TwoWay}" />
</local:SettingContainer>

<!-- Font Weight -->
<local:SettingContainer x:Name="FontWeightContainer"
x:Uid="Profile_FontWeight"
Expand Down
16 changes: 16 additions & 0 deletions src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw
Original file line number Diff line number Diff line change
Expand Up @@ -894,6 +894,22 @@
<value>Size of the font in points.</value>
<comment>A description for what the "font size" setting does. Presented near "Profile_FontSize".</comment>
</data>
<data name="Profile_LineHeight.Header" xml:space="preserve">
<value>Line height</value>
<comment>Header for a control that sets the text line height.</comment>
</data>
<data name="Profile_LineHeightBox.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<value>Line height</value>
<comment>Header for a control that sets the text line height.</comment>
</data>
<data name="Profile_LineHeight.HelpText" xml:space="preserve">
<value>Sets the height of each line in the terminal as a multiple of the font size. The default depends on your font and is usually around 1.2.</value>
<comment>A description for what the "line height" setting does. Presented near "Profile_LineHeight".</comment>
</data>
<data name="Profile_LineHeightBox.PlaceholderText" xml:space="preserve">
<value>1.2</value>
Copy link
Member

Choose a reason for hiding this comment

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

will users be confused that it says 1.2 but the default is not 1.2?

Copy link
Member Author

Choose a reason for hiding this comment

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

I felt like a placeholder made the input feel a little less confusing. 1.2 is reasonably close to the line height of most fonts (I've seen anything between about 1.15 and 1.35).

<comment>"1.2" is a decimal number.</comment>
</data>
carlos-zamora marked this conversation as resolved.
Show resolved Hide resolved
<data name="Profile_FontWeightComboBox.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<value>Font weight</value>
<comment>Name for a control to select the weight (i.e. bold, thin, etc.) of the text in the app.</comment>
Expand Down
4 changes: 3 additions & 1 deletion src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,9 @@ Model::Profile CascadiaSettings::DuplicateProfile(const Model::Profile& source)
MTSM_PROFILE_SETTINGS(DUPLICATE_PROFILE_SETTINGS)
#undef DUPLICATE_PROFILE_SETTINGS

// These two aren't in MTSM_PROFILE_SETTINGS because they're special
// These aren't in MTSM_PROFILE_SETTINGS because they're special
DUPLICATE_SETTING_MACRO(CellSizeX);
DUPLICATE_SETTING_MACRO(CellSizeY);
DUPLICATE_SETTING_MACRO(TabColor);
DUPLICATE_SETTING_MACRO(Padding);

Expand Down
20 changes: 17 additions & 3 deletions src/cascadia/TerminalSettingsModel/Profile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ static constexpr std::string_view SourceKey{ "source" };
static constexpr std::string_view HiddenKey{ "hidden" };

static constexpr std::string_view FontInfoKey{ "font" };
static constexpr std::string_view CellSizeKey{ "cellSize" };
static constexpr std::string_view CellSizeXKey{ "width" };
static constexpr std::string_view CellSizeYKey{ "height" };
static constexpr std::string_view PaddingKey{ "padding" };
static constexpr std::string_view TabColorKey{ "tabColor" };
static constexpr std::string_view UnfocusedAppearanceKey{ "unfocusedAppearance" };
Expand Down Expand Up @@ -102,6 +105,8 @@ winrt::com_ptr<Profile> Profile::CopySettings() const
profile->_Name = _Name;
profile->_Source = _Source;
profile->_Hidden = _Hidden;
profile->_CellSizeX = _CellSizeX;
profile->_CellSizeY = _CellSizeY;
profile->_TabColor = _TabColor;
profile->_Padding = _Padding;

Expand Down Expand Up @@ -171,10 +176,14 @@ void Profile::LayerJson(const Json::Value& json)
JsonUtils::GetValueForKey(json, HiddenKey, _Hidden);
JsonUtils::GetValueForKey(json, SourceKey, _Source);

if (const auto& cellSizeJSON = json[JsonKey(CellSizeKey)])
{
JsonUtils::GetValueForKey(cellSizeJSON, CellSizeXKey, _CellSizeX);
JsonUtils::GetValueForKey(cellSizeJSON, CellSizeYKey, _CellSizeY);
}
// Padding was never specified as an integer, but it was a common working mistake.
// Allow it to be permissive.
JsonUtils::GetValueForKey(json, PaddingKey, _Padding, JsonUtils::OptionalConverter<hstring, JsonUtils::PermissiveStringConverter<std::wstring>>{});

JsonUtils::GetValueForKey(json, TabColorKey, _TabColor);

#define PROFILE_SETTINGS_LAYER_JSON(type, name, jsonKey, ...) \
Expand Down Expand Up @@ -313,9 +322,14 @@ Json::Value Profile::ToJson() const
JsonUtils::SetValueForKey(json, HiddenKey, writeBasicSettings ? Hidden() : _Hidden);
JsonUtils::SetValueForKey(json, SourceKey, writeBasicSettings ? Source() : _Source);

// PermissiveStringConverter is unnecessary for serialization
if (_CellSizeX || _CellSizeY)
{
Json::Value cellSizeJSON{ Json::ValueType::objectValue };
JsonUtils::SetValueForKey(cellSizeJSON, CellSizeXKey, _CellSizeX);
JsonUtils::SetValueForKey(cellSizeJSON, CellSizeYKey, _CellSizeY);
json[JsonKey(CellSizeKey)] = std::move(cellSizeJSON);
}
JsonUtils::SetValueForKey(json, PaddingKey, _Padding);

JsonUtils::SetValueForKey(json, TabColorKey, _TabColor);

#define PROFILE_SETTINGS_TO_JSON(type, name, jsonKey, ...) \
Expand Down
2 changes: 2 additions & 0 deletions src/cascadia/TerminalSettingsModel/Profile.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
INHERITABLE_SETTING(Model::Profile, hstring, Source);
INHERITABLE_SETTING(Model::Profile, bool, Hidden, false);
INHERITABLE_SETTING(Model::Profile, guid, Guid, _GenerateGuidForProfile(Name(), Source()));
INHERITABLE_SETTING(Model::Profile, hstring, CellSizeX);
INHERITABLE_SETTING(Model::Profile, hstring, CellSizeY);
INHERITABLE_SETTING(Model::Profile, hstring, Padding, DEFAULT_PADDING);

#define PROFILE_SETTINGS_INITIALIZE(type, name, jsonKey, ...) \
Expand Down
2 changes: 2 additions & 0 deletions src/cascadia/TerminalSettingsModel/Profile.idl
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ namespace Microsoft.Terminal.Settings.Model
String EvaluatedStartingDirectory { get; };

FontConfig FontInfo { get; };
INHERITABLE_PROFILE_SETTING(String, CellSizeX);
INHERITABLE_PROFILE_SETTING(String, CellSizeY);
lhecker marked this conversation as resolved.
Show resolved Hide resolved

IAppearanceConfig DefaultAppearance { get; };
INHERITABLE_PROFILE_SETTING(IAppearanceConfig, UnfocusedAppearance);
Expand Down
2 changes: 2 additions & 0 deletions src/cascadia/TerminalSettingsModel/TerminalSettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
_FontWeight = profile.FontInfo().FontWeight();
_FontFeatures = profile.FontInfo().FontFeatures();
_FontAxes = profile.FontInfo().FontAxes();
_CellSizeX = profile.CellSizeX();
_CellSizeY = profile.CellSizeY();
_Padding = profile.Padding();

_Commandline = profile.Commandline();
Expand Down
2 changes: 2 additions & 0 deletions src/cascadia/TerminalSettingsModel/TerminalSettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
INHERITABLE_SETTING(Model::TerminalSettings, winrt::Windows::UI::Text::FontWeight, FontWeight);
INHERITABLE_SETTING(Model::TerminalSettings, IFontAxesMap, FontAxes);
INHERITABLE_SETTING(Model::TerminalSettings, IFontFeatureMap, FontFeatures);
INHERITABLE_SETTING(Model::TerminalSettings, hstring, CellSizeX);
INHERITABLE_SETTING(Model::TerminalSettings, hstring, CellSizeY);

INHERITABLE_SETTING(Model::TerminalSettings, Model::ColorScheme, AppliedColorScheme);
INHERITABLE_SETTING(Model::TerminalSettings, hstring, BackgroundImage);
Expand Down
Loading