fix: 修复特殊情况下背景绘制不正确的问题

This commit is contained in:
刘旭 2022-06-03 22:47:04 +08:00
commit 95aeb6691c
10 changed files with 97 additions and 24 deletions

View file

@ -8,6 +8,7 @@
using namespace winrt;
using namespace Windows::Foundation;
using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml::Media;
@ -54,7 +55,25 @@ void App::OnClose() {
bool App::Initialize(Magpie::Settings settings, uint64_t hwndHost) {
_settings = settings;
_hwndHost = hwndHost;
_isHostWndFocused = GetForegroundWindow() == (HWND)hwndHost;
return true;
}
event_token App::HostWndFocusChanged(EventHandler<bool> const& handler) {
return _hostWndFocusChangedEvent.add(handler);
}
void App::HostWndFocusChanged(event_token const& token) noexcept {
_hostWndFocusChangedEvent.remove(token);
}
void App::OnHostWndFocusChanged(bool isFocused) {
if (isFocused == _isHostWndFocused) {
return;
}
_isHostWndFocused = isFocused;
_hostWndFocusChangedEvent(*this, isFocused);
}
}

View file

@ -23,9 +23,20 @@ public:
return _settings;
}
event_token HostWndFocusChanged(Windows::Foundation::EventHandler<bool> const& handler);
void HostWndFocusChanged(event_token const& token) noexcept;
void OnHostWndFocusChanged(bool isFocused);
bool IsHostWndFocused() const noexcept {
return _isHostWndFocused;
}
private:
Magpie::Settings _settings;
uint64_t _hwndHost;
Magpie::Settings _settings{ nullptr };
uint64_t _hwndHost{};
event<Windows::Foundation::EventHandler<bool>> _hostWndFocusChangedEvent;
bool _isHostWndFocused = false;
};
}

View file

@ -21,5 +21,9 @@ namespace Magpie{
Settings Settings{ get; };
UInt64 HwndHost{ get; };
Boolean IsHostWndFocused { get; };
event Windows.Foundation.EventHandler<Boolean> HostWndFocusChanged;
void OnHostWndFocusChanged(Boolean isFocused);
}
}

View file

@ -33,12 +33,11 @@ MainPage::MainPage() {
_hwndHost = (HWND)Application::Current().as<App>().HwndHost();
_settings = Application::Current().as<Magpie::App>().Settings();
_micaBrush = Magpie::MicaBrush(*this);
_UpdateTheme();
_settings.ThemeChanged([this](const auto&, int) { _UpdateTheme(); });
Background(_micaBrush);
Background(Magpie::MicaBrush(*this));
}
MainPage::~MainPage() {
@ -68,10 +67,6 @@ IInspectable MainPage::RootNavigationView() {
return __super::RootNavigationView();
}
void MainPage::OnHostFocusChanged(bool isFocused) {
_micaBrush.OnHostFocusChanged(isFocused);
}
void MainPage::_UpdateTheme() {
constexpr const DWORD DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1 = 19;
constexpr const DWORD DWMWA_MICA_EFFECT = 1029;

View file

@ -18,8 +18,6 @@ namespace winrt::Magpie::implementation
Windows::Foundation::IInspectable RootNavigationView();
void OnHostFocusChanged(bool isFocused);
private:
void _UpdateTheme();
@ -32,7 +30,6 @@ namespace winrt::Magpie::implementation
Windows::UI::ViewManagement::UISettings _uiSettings;
event_token _colorChangedToken{};
Magpie::MicaBrush _micaBrush{ nullptr };
Magpie::Settings _settings{ nullptr };
std::optional<bool> _isDarkTheme;

View file

@ -5,8 +5,6 @@ namespace Magpie
{
MainPage();
void OnHostFocusChanged(Boolean isFocused);
Object RootNavigationView { get; };
}
}

View file

@ -103,17 +103,14 @@ namespace winrt::Magpie::implementation {
MicaBrush::MicaBrush(FrameworkElement root) {
_rootElement = root;
_app = Application::Current().as<App>();
_hasMica = ApiInformation::IsMethodPresent(
name_of<Compositor>(),
L"TryCreateBlurredWallpaperBackdropBrush"
);
}
void MicaBrush::OnHostFocusChanged(bool isFocused) {
_windowActivated = isFocused;
_UpdateBrush();
}
void MicaBrush::OnConnected() {
if (_settings == nullptr)
_settings = UISettings();
@ -127,12 +124,15 @@ void MicaBrush::OnConnected() {
if (!_energySaver.has_value())
_energySaver = PowerManager::EnergySaverStatus() == EnergySaverStatus::On;
_windowActivated = _app.IsHostWndFocused();
_UpdateBrush();
_highContrastChangedToken = _accessibilitySettings.HighContrastChanged({ this, &MicaBrush::_AccessibilitySettings_HighContrastChanged });
_energySaverStatusChangedToken = PowerManager::EnergySaverStatusChanged({ this, &MicaBrush::_PowerManager_EnergySaverStatusChanged });
_compositionCapabilitiesChangedToken = CompositionCapabilities::GetForCurrentView().Changed({ this, &MicaBrush::_CompositionCapabilities_Changed });
_rootElementThemeChangedToken = _rootElement.ActualThemeChanged({ this, &MicaBrush::_RootElement_ActualThemeChanged });
_hostWndFocusedChangedToken = _app.HostWndFocusChanged({this, &MicaBrush::_App_HostWndFocusedChanged});
}
void MicaBrush::OnDisconnected() {
@ -155,6 +155,9 @@ void MicaBrush::OnDisconnected() {
_rootElement.ActualThemeChanged(_rootElementThemeChangedToken);
_rootElementThemeChangedToken = {};
_app.HostWndFocusChanged(_hostWndFocusedChangedToken);
_hostWndFocusedChangedToken = {};
if (CompositionBrush() != nullptr) {
CompositionBrush().Close();
CompositionBrush(nullptr);
@ -183,6 +186,11 @@ void MicaBrush::_RootElement_ActualThemeChanged(Windows::UI::Xaml::FrameworkElem
_UpdateBrush();
}
void MicaBrush::_App_HostWndFocusedChanged(IInspectable const&, bool isFocused) {
_windowActivated = isFocused;
_UpdateBrush();
}
void MicaBrush::_UpdateBrush() {
if (_settings == nullptr || _accessibilitySettings == nullptr) {
return;

View file

@ -8,8 +8,6 @@ namespace winrt::Magpie::implementation {
struct MicaBrush : MicaBrushT<MicaBrush> {
MicaBrush(Windows::UI::Xaml::FrameworkElement root);
void OnHostFocusChanged(bool isFocused);
void OnConnected();
void OnDisconnected();
@ -32,6 +30,12 @@ private:
Windows::UI::Xaml::FrameworkElement const&,
Windows::Foundation::IInspectable const&
);
void _App_HostWndFocusedChanged(
Windows::Foundation::IInspectable const&,
bool isFocused
);
App _app{ nullptr };
Windows::UI::Xaml::FrameworkElement _rootElement{ nullptr };
bool _windowActivated = false;
@ -46,6 +50,7 @@ private:
winrt::event_token _energySaverStatusChangedToken{};
winrt::event_token _compositionCapabilitiesChangedToken{};
winrt::event_token _rootElementThemeChangedToken{};
winrt::event_token _hostWndFocusedChangedToken{};
};
}

View file

@ -1,9 +1,8 @@
namespace Magpie
{
[default_interface]
runtimeclass MicaBrush : Windows.UI.Xaml.Media.XamlCompositionBrushBase
{
MicaBrush(Windows.UI.Xaml.FrameworkElement root);
void OnHostFocusChanged(Boolean isFocused);
}
}

View file

@ -20,6 +20,8 @@ using namespace Magpie;
static constexpr const wchar_t* XAML_HOST_CLASS_NAME = L"Magpie_XamlHost";
static constexpr const wchar_t* MUTEX_NAME = L"{4C416227-4A30-4A2F-8F23-8701544DD7D6}";
static constexpr UINT CHECK_FORGROUND_TIMER_ID = 1;
bool XamlApp::Initialize(HINSTANCE hInstance) {
_hMutex.reset(CreateMutex(nullptr, TRUE, MUTEX_NAME));
@ -153,6 +155,19 @@ bool XamlApp::Initialize(HINSTANCE hInstance) {
}
});
{
// SetTimer 之前推荐先调用 SetUserObjectInformation
BOOL value = FALSE;
if (!SetUserObjectInformation(GetCurrentProcess(), UOI_TIMERPROC_EXCEPTION_SUPPRESSION, &value, sizeof(value))) {
Logger::Get().Win32Error("SetUserObjectInformation 失败");
}
// 监听 WM_ACTIVATE 不完全可靠,因此定期检查前台窗口以确保背景绘制正确
if (SetTimer(_hwndXamlHost, CHECK_FORGROUND_TIMER_ID, 250, nullptr) == 0) {
Logger::Get().Win32Error("SetTimer 失败");
}
}
return true;
}
@ -193,6 +208,14 @@ void XamlApp::_OnResize() {
LRESULT XamlApp::_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch (message) {
case WM_HOTKEY:
{
if (message >= 0) {
return 0;
}
break;
}
case WM_KEYDOWN:
{
if (wParam == VK_TAB) {
@ -247,17 +270,31 @@ LRESULT XamlApp::_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
case WM_ACTIVATE:
{
if (LOWORD(wParam) != WA_INACTIVE) {
_mainPage.OnHostFocusChanged(true);
_uwpApp.OnHostWndFocusChanged(true);
if (_hwndXamlIsland) {
SetFocus(_hwndXamlIsland);
}
} else {
_mainPage.OnHostFocusChanged(false);
_uwpApp.OnHostWndFocusChanged(false);
_CloseAllXamlPopups();
}
return 0;
}
case WM_TIMER:
{
if (wParam == CHECK_FORGROUND_TIMER_ID) {
if (GetForegroundWindow() == _hwndXamlHost) {
_uwpApp.OnHostWndFocusChanged(true);
} else {
_uwpApp.OnHostWndFocusChanged(false);
_CloseAllXamlPopups();
}
return 0;
}
break;
}
case WM_MOVING:
{
_CloseAllXamlPopups();