Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions .github/actions/spelling/expect/expect.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1628,6 +1628,7 @@ sysparams
SYSTEMHAND
SYSTEMMENU
SYSTEMTIME
TABBEDWINDOW
tabview
taef
TARG
Expand Down
18 changes: 15 additions & 3 deletions doc/cascadia/profiles.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -2048,9 +2048,21 @@
"type": "string"
},
"useMica": {
"description": "True if the Terminal should use a Mica backdrop for the window. This will apply underneath all controls (including the terminal panes and the titlebar)",
"type": "boolean",
"default": false
"default": "none",
"description": "Sets the backdrop material for the window, applied underneath all controls (including the terminal panes and the titlebar). Possible values:\n -\"mica\" (the Mica material)\n -\"micaAlt\" (the Mica Alt material)\n -\"none\" (no backdrop).\ntrue and false are accepted as synonyms for \"mica\" and \"none\" respectively.",
"oneOf": [
{
"enum": [
"none",
"mica",
"micaAlt"
],
"type": "string"
},
{
"type": "boolean"
}
]
},
"experimental.rainbowFrame": {
"description": "When enabled, the frame of the window will cycle through all the colors. Enabling this will override the `frame` and `unfocusedFrame` settings.",
Expand Down
2 changes: 1 addition & 1 deletion src/cascadia/TerminalSettingsEditor/MainPage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1169,7 +1169,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
// that our theme is different than the app's.
const bool actuallyUseMica = isMicaAvailable && (appTheme == requestedTheme);

const auto bgKey = (theme.Window() != nullptr && theme.Window().UseMica()) && actuallyUseMica ?
const auto bgKey = (theme.Window() != nullptr && theme.Window().UseMica() != winrt::Microsoft::Terminal::Settings::Model::MicaStyle::None) && actuallyUseMica ?
L"SettingsPageMicaBackground" :
L"SettingsPageBackground";

Expand Down
12 changes: 6 additions & 6 deletions src/cascadia/TerminalSettingsModel/MTSMSettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,12 +157,12 @@ Author(s):
X(winrt::Microsoft::Terminal::Settings::Model::TabRowTheme, TabRow, "tabRow", nullptr) \
X(winrt::Microsoft::Terminal::Settings::Model::TabTheme, Tab, "tab", nullptr)

#define MTSM_THEME_WINDOW_SETTINGS(X) \
X(winrt::Windows::UI::Xaml::ElementTheme, RequestedTheme, "applicationTheme", winrt::Windows::UI::Xaml::ElementTheme::Default) \
X(winrt::Microsoft::Terminal::Settings::Model::ThemeColor, Frame, "frame", nullptr) \
X(winrt::Microsoft::Terminal::Settings::Model::ThemeColor, UnfocusedFrame, "unfocusedFrame", nullptr) \
X(bool, RainbowFrame, "experimental.rainbowFrame", false) \
X(bool, UseMica, "useMica", false) \
#define MTSM_THEME_WINDOW_SETTINGS(X) \
X(winrt::Windows::UI::Xaml::ElementTheme, RequestedTheme, "applicationTheme", winrt::Windows::UI::Xaml::ElementTheme::Default) \
X(winrt::Microsoft::Terminal::Settings::Model::ThemeColor, Frame, "frame", nullptr) \
X(winrt::Microsoft::Terminal::Settings::Model::ThemeColor, UnfocusedFrame, "unfocusedFrame", nullptr) \
X(bool, RainbowFrame, "experimental.rainbowFrame", false) \
X(winrt::Microsoft::Terminal::Settings::Model::MicaStyle, UseMica, "useMica", winrt::Microsoft::Terminal::Settings::Model::MicaStyle::None) \
X(bool, ShowWorkspacesButton, "showWorkspacesButton", true)

#define MTSM_THEME_SETTINGS_SETTINGS(X) \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,31 @@ JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Settings::Model::CloseOnExitMode)
using EnumMapper::TypeDescription;
};

JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Settings::Model::MicaStyle)
{
JSON_MAPPINGS(3) = {
pair_type{ "none", ValueType::None },
pair_type{ "mica", ValueType::Mica },
pair_type{ "micaAlt", ValueType::MicaAlt },
};

// Override mapping parser to add boolean parsing (useMica used to be a bool)
::winrt::Microsoft::Terminal::Settings::Model::MicaStyle FromJson(const Json::Value& json)
{
if (json.isBool())
{
return json.asBool() ? ValueType::Mica : ValueType::None;
}
return EnumMapper::FromJson(json);
}

bool CanConvert(const Json::Value& json)
{
return EnumMapper::CanConvert(json) || json.isBool();
}
using EnumMapper::TypeDescription;
};

// This specialization isn't using JSON_ENUM_MAPPER because we need to have a different
// value type (unsigned int) and return type (FontWeight struct). JSON_ENUM_MAPPER
// expects that the value type _is_ the return type.
Expand Down
9 changes: 8 additions & 1 deletion src/cascadia/TerminalSettingsModel/Theme.idl
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ namespace Microsoft.Terminal.Settings.Model
ActiveOnly
};

enum MicaStyle
{
None,
Mica,
MicaAlt
};

[default_interface] runtimeclass ThemePair
{
ThemePair();
Expand Down Expand Up @@ -60,7 +67,7 @@ namespace Microsoft.Terminal.Settings.Model

runtimeclass WindowTheme {
Windows.UI.Xaml.ElementTheme RequestedTheme { get; };
Boolean UseMica { get; };
MicaStyle UseMica { get; };
Boolean RainbowFrame { get; };
Boolean ShowWorkspacesButton { get; };
ThemeColor Frame { get; };
Expand Down
72 changes: 71 additions & 1 deletion src/cascadia/UnitTests_SettingsModel/ThemeTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ namespace SettingsModelUnitTests
TEST_CLASS(ThemeTests);

TEST_METHOD(ParseSimpleTheme);
TEST_METHOD(ParseMicaStyle);
TEST_METHOD(ParseEmptyTheme);
TEST_METHOD(ParseNoWindowTheme);
TEST_METHOD(ParseNullWindowTheme);
Expand Down Expand Up @@ -68,7 +69,76 @@ namespace SettingsModelUnitTests

VERIFY_IS_NOT_NULL(theme->Window());
VERIFY_ARE_EQUAL(winrt::Windows::UI::Xaml::ElementTheme::Light, theme->Window().RequestedTheme());
VERIFY_ARE_EQUAL(true, theme->Window().UseMica());
VERIFY_ARE_EQUAL(Settings::Model::MicaStyle::Mica, theme->Window().UseMica());
}

void ThemeTests::ParseMicaStyle()
{
Log::Comment(L"Verify useMica parses the MicaStyle enum, plus booleans for back-compat.");

{
static constexpr std::string_view noneTheme{ R"({
"name": "none",
"window":
{
"useMica": "none"
}
})" };
const auto schemeObject = VerifyParseSucceeded(noneTheme);
auto theme = Theme::FromJson(schemeObject);
VERIFY_IS_NOT_NULL(theme->Window());
VERIFY_ARE_EQUAL(Settings::Model::MicaStyle::None, theme->Window().UseMica());
}
{
static constexpr std::string_view micaTheme{ R"({
"name": "mica",
"window":
{
"useMica": "mica"
}
})" };
const auto schemeObject = VerifyParseSucceeded(micaTheme);
auto theme = Theme::FromJson(schemeObject);
VERIFY_ARE_EQUAL(Settings::Model::MicaStyle::Mica, theme->Window().UseMica());
}
{
static constexpr std::string_view micaAltTheme{ R"({
"name": "micaAlt",
"window":
{
"useMica": "micaAlt"
}
})" };
const auto schemeObject = VerifyParseSucceeded(micaAltTheme);
auto theme = Theme::FromJson(schemeObject);
VERIFY_ARE_EQUAL(Settings::Model::MicaStyle::MicaAlt, theme->Window().UseMica());
}

Log::Comment(L"Back-compat: booleans map to Mica / None.");
{
static constexpr std::string_view trueTheme{ R"({
"name": "true",
"window":
{
"useMica": true
}
})" };
const auto schemeObject = VerifyParseSucceeded(trueTheme);
auto theme = Theme::FromJson(schemeObject);
VERIFY_ARE_EQUAL(Settings::Model::MicaStyle::Mica, theme->Window().UseMica());
}
{
static constexpr std::string_view falseTheme{ R"({
"name": "false",
"window":
{
"useMica": false
}
})" };
const auto schemeObject = VerifyParseSucceeded(falseTheme);
auto theme = Theme::FromJson(schemeObject);
VERIFY_ARE_EQUAL(Settings::Model::MicaStyle::None, theme->Window().UseMica());
}
}

void ThemeTests::ParseEmptyTheme()
Expand Down
2 changes: 1 addition & 1 deletion src/cascadia/WindowsTerminal/AppHost.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1002,7 +1002,7 @@ void AppHost::_updateTheme()
const auto colorOpacity = b ? color.A / 255.0 : 0.0;
const auto brushOpacity = _opacityFromBrush(b);
const auto opacity = std::min(colorOpacity, brushOpacity);
_window->UseMica(windowTheme ? windowTheme.UseMica() : false, opacity);
_window->UseMica(windowTheme ? windowTheme.UseMica() : winrt::Microsoft::Terminal::Settings::Model::MicaStyle::None, opacity);

// This is a hack to make the window borders dark instead of light.
// It must be done before WM_NCPAINT so that the borders are rendered with
Expand Down
16 changes: 14 additions & 2 deletions src/cascadia/WindowsTerminal/IslandWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1844,7 +1844,7 @@ void IslandWindow::UseDarkTheme(const bool v)
std::ignore = DwmSetWindowAttribute(GetHandle(), DWMWA_USE_IMMERSIVE_DARK_MODE, &attribute, sizeof(attribute));
}

void IslandWindow::UseMica(const bool newValue, const double /*titlebarOpacity*/)
void IslandWindow::UseMica(const winrt::Microsoft::Terminal::Settings::Model::MicaStyle newValue, const double /*titlebarOpacity*/)
{
// This block of code enables Mica for our window. By all accounts, this
// version of the code will only work on Windows 11, SV2. There's a slightly
Expand All @@ -1853,7 +1853,19 @@ void IslandWindow::UseMica(const bool newValue, const double /*titlebarOpacity*/
// This API was only publicly supported as of Windows 11 SV2, 22621. Before
// that version, this API will just return an error and do nothing silently.

const int attribute = newValue ? DWMSBT_MAINWINDOW : DWMSBT_NONE;
int attribute = DWMSBT_NONE;
switch (newValue)
{
case winrt::Microsoft::Terminal::Settings::Model::MicaStyle::Mica:
attribute = DWMSBT_MAINWINDOW; // "Mica"
break;
case winrt::Microsoft::Terminal::Settings::Model::MicaStyle::MicaAlt:
attribute = DWMSBT_TABBEDWINDOW; // "Mica Alt"
break;
default: // None
attribute = DWMSBT_NONE;
break;
}
std::ignore = DwmSetWindowAttribute(GetHandle(), DWMWA_SYSTEMBACKDROP_TYPE, &attribute, sizeof(attribute));
}

Expand Down
2 changes: 1 addition & 1 deletion src/cascadia/WindowsTerminal/IslandWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ class IslandWindow :
void RemoveFromSystemMenu(const winrt::hstring& itemLabel);

void UseDarkTheme(const bool v);
virtual void UseMica(const bool newValue, const double titlebarOpacity);
virtual void UseMica(const winrt::Microsoft::Terminal::Settings::Model::MicaStyle newValue, const double titlebarOpacity);

til::event<winrt::delegate<>> DragRegionClicked;
til::event<winrt::delegate<>> WindowCloseButtonClicked;
Expand Down
4 changes: 2 additions & 2 deletions src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1195,12 +1195,12 @@ void NonClientIslandWindow::SetTitlebarBackground(winrt::Windows::UI::Xaml::Medi
_titlebar.Background(brush);
}

void NonClientIslandWindow::UseMica(const bool newValue, const double titlebarOpacity)
void NonClientIslandWindow::UseMica(const winrt::Microsoft::Terminal::Settings::Model::MicaStyle newValue, const double titlebarOpacity)
{
// Stash internally if we're using Mica. If we aren't, we don't want to
// totally blow away our titlebar with DwmExtendFrameIntoClientArea,
// especially on Windows 10
_useMica = newValue;
_useMica = newValue != winrt::Microsoft::Terminal::Settings::Model::MicaStyle::None;
_titlebarOpacity = titlebarOpacity;

IslandWindow::UseMica(newValue, titlebarOpacity);
Expand Down
2 changes: 1 addition & 1 deletion src/cascadia/WindowsTerminal/NonClientIslandWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class NonClientIslandWindow : public IslandWindow
void SetTitlebarBackground(winrt::Windows::UI::Xaml::Media::Brush brush);
void SetShowTabsFullscreen(const bool newShowTabsFullscreen) override;

virtual void UseMica(const bool newValue, const double titlebarOpacity) override;
virtual void UseMica(const winrt::Microsoft::Terminal::Settings::Model::MicaStyle newValue, const double titlebarOpacity) override;

private:
std::optional<til::point> _oldIslandPos;
Expand Down
Loading