[Always on top] Transparent border (#28127)

This commit is contained in:
Seraphima Zykova
2023-08-25 11:31:51 +03:00
committed by GitHub
parent 738072f508
commit b3532b8c91
10 changed files with 66 additions and 18 deletions

View File

@@ -90,10 +90,10 @@ void FrameDrawer::Show()
Render(); Render();
} }
void FrameDrawer::SetBorderRect(RECT windowRect, COLORREF color, int thickness, float radius) void FrameDrawer::SetBorderRect(RECT windowRect, COLORREF rgb, float alpha, int thickness, float radius)
{ {
auto newSceneRect = DrawableRect{ auto newSceneRect = DrawableRect{
.borderColor = ConvertColor(color), .borderColor = ConvertColor(rgb, alpha),
.thickness = thickness, .thickness = thickness,
}; };
@@ -175,12 +175,12 @@ IDWriteFactory* FrameDrawer::GetWriteFactory()
return pDWriteFactory; return pDWriteFactory;
} }
D2D1_COLOR_F FrameDrawer::ConvertColor(COLORREF color) D2D1_COLOR_F FrameDrawer::ConvertColor(COLORREF color, float alpha)
{ {
return D2D1::ColorF(GetRValue(color) / 255.f, return D2D1::ColorF(GetRValue(color) / 255.f,
GetGValue(color) / 255.f, GetGValue(color) / 255.f,
GetBValue(color) / 255.f, GetBValue(color) / 255.f,
1.f); alpha);
} }
D2D1_ROUNDED_RECT FrameDrawer::ConvertRect(RECT rect, int thickness, float radius) D2D1_ROUNDED_RECT FrameDrawer::ConvertRect(RECT rect, int thickness, float radius)

View File

@@ -18,7 +18,7 @@ public:
void Show(); void Show();
void Hide(); void Hide();
void SetBorderRect(RECT windowRect, COLORREF color, int thickness, float radius); void SetBorderRect(RECT windowRect, COLORREF rgb, float alpha, int thickness, float radius);
private: private:
bool CreateRenderTargets(const RECT& clientRect); bool CreateRenderTargets(const RECT& clientRect);
@@ -33,7 +33,7 @@ private:
static ID2D1Factory* GetD2DFactory(); static ID2D1Factory* GetD2DFactory();
static IDWriteFactory* GetWriteFactory(); static IDWriteFactory* GetWriteFactory();
static D2D1_COLOR_F ConvertColor(COLORREF color); static D2D1_COLOR_F ConvertColor(COLORREF color, float alpha);
static D2D1_ROUNDED_RECT ConvertRect(RECT rect, int thickness, float radius); static D2D1_ROUNDED_RECT ConvertRect(RECT rect, int thickness, float radius);
static D2D1_RECT_F ConvertRect(RECT rect, int thickness); static D2D1_RECT_F ConvertRect(RECT rect, int thickness);
void Render(); void Render();

View File

@@ -17,6 +17,7 @@ namespace NonLocalizable
const static wchar_t* FrameEnabledID = L"frame-enabled"; const static wchar_t* FrameEnabledID = L"frame-enabled";
const static wchar_t* FrameThicknessID = L"frame-thickness"; const static wchar_t* FrameThicknessID = L"frame-thickness";
const static wchar_t* FrameColorID = L"frame-color"; const static wchar_t* FrameColorID = L"frame-color";
const static wchar_t* FrameOpacityID = L"frame-opacity";
const static wchar_t* BlockInGameModeID = L"do-not-activate-on-game-mode"; const static wchar_t* BlockInGameModeID = L"do-not-activate-on-game-mode";
const static wchar_t* ExcludedAppsID = L"excluded-apps"; const static wchar_t* ExcludedAppsID = L"excluded-apps";
const static wchar_t* FrameAccentColor = L"frame-accent-color"; const static wchar_t* FrameAccentColor = L"frame-accent-color";
@@ -134,6 +135,16 @@ void AlwaysOnTopSettings::LoadSettings()
} }
} }
if (const auto jsonVal = values.get_int_value(NonLocalizable::FrameOpacityID))
{
auto val = *jsonVal;
if (m_settings.frameOpacity != val)
{
m_settings.frameOpacity = val;
NotifyObservers(SettingId::FrameOpacity);
}
}
if (const auto jsonVal = values.get_bool_value(NonLocalizable::FrameEnabledID)) if (const auto jsonVal = values.get_bool_value(NonLocalizable::FrameEnabledID))
{ {
auto val = *jsonVal; auto val = *jsonVal;

View File

@@ -21,6 +21,7 @@ struct Settings
bool blockInGameMode = true; bool blockInGameMode = true;
bool frameAccentColor = true; bool frameAccentColor = true;
int frameThickness = 15; int frameThickness = 15;
int frameOpacity = 100;
COLORREF frameColor = RGB(0, 173, 239); COLORREF frameColor = RGB(0, 173, 239);
std::vector<std::wstring> excludedApps{}; std::vector<std::wstring> excludedApps{};
}; };

View File

@@ -7,6 +7,7 @@ enum class SettingId
FrameEnabled, FrameEnabled,
FrameThickness, FrameThickness,
FrameColor, FrameColor,
FrameOpacity,
BlockInGameMode, BlockInGameMode,
ExcludeApps, ExcludeApps,
FrameAccentColor, FrameAccentColor,

View File

@@ -33,7 +33,7 @@ std::optional<RECT> GetFrameRect(HWND window)
} }
WindowBorder::WindowBorder(HWND window) : WindowBorder::WindowBorder(HWND window) :
SettingsObserver({ SettingId::FrameColor, SettingId::FrameThickness, SettingId::FrameAccentColor, SettingId::RoundCornersEnabled }), SettingsObserver({ SettingId::FrameColor, SettingId::FrameThickness, SettingId::FrameAccentColor, SettingId::FrameOpacity, SettingId::RoundCornersEnabled }),
m_window(nullptr), m_window(nullptr),
m_trackingWindow(window), m_trackingWindow(window),
m_frameDrawer(nullptr) m_frameDrawer(nullptr)
@@ -113,6 +113,14 @@ bool WindowBorder::Init(HINSTANCE hinstance)
return false; return false;
} }
// make window transparent
int const pos = -GetSystemMetrics(SM_CXVIRTUALSCREEN) - 8;
if (wil::unique_hrgn hrgn{ CreateRectRgn(pos, 0, (pos + 1), 1) })
{
DWM_BLURBEHIND bh = { DWM_BB_ENABLE | DWM_BB_BLURREGION, TRUE, hrgn.get(), FALSE };
DwmEnableBlurBehindWindow(m_window, &bh);
}
if (!SetLayeredWindowAttributes(m_window, RGB(0, 0, 0), 0, LWA_COLORKEY)) if (!SetLayeredWindowAttributes(m_window, RGB(0, 0, 0), 0, LWA_COLORKEY))
{ {
return false; return false;
@@ -193,6 +201,7 @@ void WindowBorder::UpdateBorderProperties() const
color = AlwaysOnTopSettings::settings().frameColor; color = AlwaysOnTopSettings::settings().frameColor;
} }
float opacity = AlwaysOnTopSettings::settings().frameOpacity / 100.0f;
float scalingFactor = ScalingUtils::ScalingFactor(m_trackingWindow); float scalingFactor = ScalingUtils::ScalingFactor(m_trackingWindow);
float thickness = AlwaysOnTopSettings::settings().frameThickness * scalingFactor; float thickness = AlwaysOnTopSettings::settings().frameThickness * scalingFactor;
float cornerRadius = 0.0; float cornerRadius = 0.0;
@@ -201,7 +210,7 @@ void WindowBorder::UpdateBorderProperties() const
cornerRadius = WindowCornerUtils::CornersRadius(m_trackingWindow) * scalingFactor; cornerRadius = WindowCornerUtils::CornersRadius(m_trackingWindow) * scalingFactor;
} }
m_frameDrawer->SetBorderRect(frameRect, color, static_cast<int>(thickness), cornerRadius); m_frameDrawer->SetBorderRect(frameRect, color, opacity, static_cast<int>(thickness), cornerRadius);
} }
LRESULT WindowBorder::WndProc(UINT message, WPARAM wparam, LPARAM lparam) noexcept LRESULT WindowBorder::WndProc(UINT message, WPARAM wparam, LPARAM lparam) noexcept
@@ -267,22 +276,14 @@ void WindowBorder::SettingsUpdate(SettingId id)
break; break;
case SettingId::FrameColor: case SettingId::FrameColor:
{
UpdateBorderProperties();
}
break;
case SettingId::FrameAccentColor: case SettingId::FrameAccentColor:
{ case SettingId::FrameOpacity:
UpdateBorderProperties();
}
break;
case SettingId::RoundCornersEnabled: case SettingId::RoundCornersEnabled:
{ {
UpdateBorderProperties(); UpdateBorderProperties();
} }
break; break;
default: default:
break; break;
} }

View File

@@ -15,6 +15,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library
public const int DefaultFrameThickness = 15; public const int DefaultFrameThickness = 15;
public const string DefaultFrameColor = "#0099cc"; public const string DefaultFrameColor = "#0099cc";
public const bool DefaultFrameAccentColor = true; public const bool DefaultFrameAccentColor = true;
public const int DefaultFrameOpacity = 100;
public const bool DefaultSoundEnabled = true; public const bool DefaultSoundEnabled = true;
public const bool DefaultDoNotActivateOnGameMode = true; public const bool DefaultDoNotActivateOnGameMode = true;
public const bool DefaultRoundCornersEnabled = true; public const bool DefaultRoundCornersEnabled = true;
@@ -26,6 +27,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library
FrameThickness = new IntProperty(DefaultFrameThickness); FrameThickness = new IntProperty(DefaultFrameThickness);
FrameColor = new StringProperty(DefaultFrameColor); FrameColor = new StringProperty(DefaultFrameColor);
FrameAccentColor = new BoolProperty(DefaultFrameAccentColor); FrameAccentColor = new BoolProperty(DefaultFrameAccentColor);
FrameOpacity = new IntProperty(DefaultFrameOpacity);
SoundEnabled = new BoolProperty(DefaultSoundEnabled); SoundEnabled = new BoolProperty(DefaultSoundEnabled);
DoNotActivateOnGameMode = new BoolProperty(DefaultDoNotActivateOnGameMode); DoNotActivateOnGameMode = new BoolProperty(DefaultDoNotActivateOnGameMode);
RoundCornersEnabled = new BoolProperty(DefaultRoundCornersEnabled); RoundCornersEnabled = new BoolProperty(DefaultRoundCornersEnabled);
@@ -44,6 +46,9 @@ namespace Microsoft.PowerToys.Settings.UI.Library
[JsonPropertyName("frame-color")] [JsonPropertyName("frame-color")]
public StringProperty FrameColor { get; set; } public StringProperty FrameColor { get; set; }
[JsonPropertyName("frame-opacity")]
public IntProperty FrameOpacity { get; set; }
[JsonPropertyName("frame-accent-color")] [JsonPropertyName("frame-accent-color")]
public BoolProperty FrameAccentColor { get; set; } public BoolProperty FrameAccentColor { get; set; }

View File

@@ -80,6 +80,15 @@
Visibility="{x:Bind Mode=OneWay, Path=ViewModel.FrameAccentColor, Converter={StaticResource ReverseBoolToVisibilityConverter}}"> Visibility="{x:Bind Mode=OneWay, Path=ViewModel.FrameAccentColor, Converter={StaticResource ReverseBoolToVisibilityConverter}}">
<controls:ColorPickerButton SelectedColor="{x:Bind Path=ViewModel.FrameColor, Mode=TwoWay}" /> <controls:ColorPickerButton SelectedColor="{x:Bind Path=ViewModel.FrameColor, Mode=TwoWay}" />
</labs:SettingsCard> </labs:SettingsCard>
<labs:SettingsCard
x:Uid="AlwaysOnTop_FrameOpacity"
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.FrameEnabled}">
<Slider
MinWidth="{StaticResource SettingActionControlMinWidth}"
Maximum="100"
Minimum="0"
Value="{x:Bind Mode=TwoWay, Path=ViewModel.FrameOpacity}" />
</labs:SettingsCard>
<labs:SettingsCard <labs:SettingsCard
x:Uid="AlwaysOnTop_FrameThickness" x:Uid="AlwaysOnTop_FrameThickness"
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.FrameEnabled}"> IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.FrameEnabled}">

View File

@@ -3655,4 +3655,7 @@ Activate by holding the key for the character you want to add an accent to, then
<data name="Run_PluginUseFindMorePlugins.Content" xml:space="preserve"> <data name="Run_PluginUseFindMorePlugins.Content" xml:space="preserve">
<value>Find more plugins</value> <value>Find more plugins</value>
</data> </data>
<data name="AlwaysOnTop_FrameOpacity.Header" xml:space="preserve">
<value>Opacity (%)</value>
</data>
</root> </root>

View File

@@ -55,6 +55,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
_frameEnabled = Settings.Properties.FrameEnabled.Value; _frameEnabled = Settings.Properties.FrameEnabled.Value;
_frameThickness = Settings.Properties.FrameThickness.Value; _frameThickness = Settings.Properties.FrameThickness.Value;
_frameColor = Settings.Properties.FrameColor.Value; _frameColor = Settings.Properties.FrameColor.Value;
_frameOpacity = Settings.Properties.FrameOpacity.Value;
_frameAccentColor = Settings.Properties.FrameAccentColor.Value; _frameAccentColor = Settings.Properties.FrameAccentColor.Value;
_soundEnabled = Settings.Properties.SoundEnabled.Value; _soundEnabled = Settings.Properties.SoundEnabled.Value;
_doNotActivateOnGameMode = Settings.Properties.DoNotActivateOnGameMode.Value; _doNotActivateOnGameMode = Settings.Properties.DoNotActivateOnGameMode.Value;
@@ -188,6 +189,21 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
} }
} }
public int FrameOpacity
{
get => _frameOpacity;
set
{
if (value != _frameOpacity)
{
_frameOpacity = value;
Settings.Properties.FrameOpacity.Value = value;
NotifyPropertyChanged();
}
}
}
public bool SoundEnabled public bool SoundEnabled
{ {
get => _soundEnabled; get => _soundEnabled;
@@ -293,6 +309,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
private int _frameThickness; private int _frameThickness;
private string _frameColor; private string _frameColor;
private bool _frameAccentColor; private bool _frameAccentColor;
private int _frameOpacity;
private bool _soundEnabled; private bool _soundEnabled;
private bool _doNotActivateOnGameMode; private bool _doNotActivateOnGameMode;
private bool _roundCornersEnabled; private bool _roundCornersEnabled;