Bug 1934439 - Make the mica prefs toggle-able at runtime. r=win-reviewers,rkraesig

Not particularly pretty but this will do.

Differential Revision: https://phabricator.services.mozilla.com/D238705
This commit is contained in:
Emilio Cobos Álvarez
2025-02-20 22:35:19 +00:00
parent 217fd47316
commit 88d0eee4d0
6 changed files with 88 additions and 18 deletions

View File

@@ -6,6 +6,14 @@
<script>
const SHEET = document.querySelector('style');
let lazy = {};
ChromeUtils.defineESModuleGetters(lazy, {
WindowsVersionInfo:
"resource://gre/modules/components-utils/WindowsVersionInfo.sys.mjs",
});
SimpleTest.waitForExplicitFinish();
function expect(q, shouldBeKnown) {
@@ -92,6 +100,26 @@ expectUnkown("(-moz-platform: )");
await testMozPref('-moz-pref("foo.bar.str")', "foo.bar.str", "foo", "");
await testMozPref('-moz-pref("foo.bar.int", 1)', "foo.bar.int", 1, 2);
await testMozPref('-moz-pref("foo.bar.int")', "foo.bar.int", 1, 0);
let supportsMica = matchMedia('(-moz-platform: windows)').matches && lazy.WindowsVersionInfo.get().buildNumber >= 22621;
info(`Mica supported: ${supportsMica}`);
for (let [query, pref] of [['(-moz-windows-mica)', 'widget.windows.mica'], ['(-moz-windows-mica-popups)', 'widget.windows.mica.popups']]) {
let prefEnabled = SpecialPowers.getBoolPref("widget.windows.mica", false);
let mediaList = matchMedia(query);
is(mediaList.matches, supportsMica && prefEnabled, `Mica support is as expected ${query}`);
let change = new Promise(r => {
mediaList.addEventListener("change", r, { once: true });
});
await SpecialPowers.pushPrefEnv({
set:[[pref, !prefEnabled]],
});
if (supportsMica) {
await change;
}
is(mediaList.matches, supportsMica && !prefEnabled, `Mica query works dynamically if appropriate ${query}`);
await SpecialPowers.popPrefEnv();
}
SimpleTest.finish();
}());
</script>

View File

@@ -18454,14 +18454,13 @@
- name: widget.windows.mica
type: bool
value: false
mirror: once
mirror: always
# Whether we use the mica backdrop for popups. Off by default for now.
# TODO(emilio): Make these toggleable at runtime?
- name: widget.windows.mica.popups
type: bool
value: false
mirror: once
mirror: always
#endif
# Whether to disable SwipeTracker (e.g. swipe-to-nav).

View File

@@ -68,8 +68,7 @@ mozilla::LazyLogModule gWindowsLog("Widget");
using namespace mozilla::gfx;
namespace mozilla {
namespace widget {
namespace mozilla::widget {
#ifdef MOZ_PLACES
NS_IMPL_ISUPPORTS(myDownloadObserver, nsIDownloadObserver)
@@ -2005,16 +2004,43 @@ bool WinUtils::GetTimezoneName(wchar_t* aBuffer) {
return true;
}
static constexpr nsLiteralCString kMicaPrefs[] = {
"widget.windows.mica"_ns,
"widget.windows.mica.popups"_ns,
};
static BOOL CALLBACK UpdateMicaInHwnd(HWND aHwnd, LPARAM aLParam) {
if (RefPtr<nsWindow> win = WinUtils::GetNSWindowPtr(aHwnd)) {
win->UpdateMicaBackdrop(/* aForce = */ true);
}
return TRUE;
}
static void UpdateMicaInAllWindows(const char*, void*) {
::EnumWindows(&UpdateMicaInHwnd, 0);
LookAndFeel::NotifyChangedAllWindows(
widget::ThemeChangeKind::MediaQueriesOnly);
}
bool WinUtils::MicaAvailable() {
static bool sAvailable = [] {
if (!IsWin1122H2OrLater()) {
return false;
}
for (const auto& pref : kMicaPrefs) {
Preferences::RegisterCallback(UpdateMicaInAllWindows, pref);
}
return true;
}();
return sAvailable;
}
bool WinUtils::MicaEnabled() {
static bool sEnabled =
IsWin1122H2OrLater() && StaticPrefs::widget_windows_mica_AtStartup();
return sEnabled;
return MicaAvailable() && StaticPrefs::widget_windows_mica();
}
bool WinUtils::MicaPopupsEnabled() {
static bool sEnabled = IsWin1122H2OrLater() &&
StaticPrefs::widget_windows_mica_popups_AtStartup();
return sEnabled;
return MicaAvailable() && StaticPrefs::widget_windows_mica_popups();
}
// There are undocumented APIs to query/change the system DPI settings found by
@@ -2225,5 +2251,4 @@ ScopedRtlShimWindow::~ScopedRtlShimWindow() {
}
}
} // namespace widget
} // namespace mozilla
} // namespace mozilla::widget

View File

@@ -544,6 +544,7 @@ class WinUtils {
static bool GetClassName(HWND aHwnd, nsAString& aName);
static bool MicaAvailable();
static bool MicaEnabled();
static bool MicaPopupsEnabled();

View File

@@ -668,6 +668,7 @@ nsWindow::nsWindow(bool aIsChildWindow)
mFrameState(std::in_place, this),
mIsChildWindow(aIsChildWindow),
mPIPWindow(false),
mMicaBackdrop(false),
mLastPaintEndTime(TimeStamp::Now()),
mCachedHitTestTime(TimeStamp::Now()),
mSizeConstraintsScale(GetDefaultScale().scale),
@@ -2524,14 +2525,25 @@ void nsWindow::SetColorScheme(const Maybe<ColorScheme>& aScheme) {
}
void nsWindow::SetMicaBackdrop(bool aEnabled) {
const bool micaEnabled =
IsPopup() ? WinUtils::MicaPopupsEnabled() : WinUtils::MicaEnabled();
if (!micaEnabled) {
if (aEnabled == mMicaBackdrop) {
return;
}
mMicaBackdrop = aEnabled;
UpdateMicaBackdrop();
}
void nsWindow::UpdateMicaBackdrop(bool aForce) {
const bool micaEnabled =
IsPopup() ? WinUtils::MicaPopupsEnabled() : WinUtils::MicaEnabled();
if (!micaEnabled && !aForce) {
return;
}
const bool useBackdrop = mMicaBackdrop && micaEnabled;
const DWM_SYSTEMBACKDROP_TYPE backdrop = [&] {
if (!aEnabled) {
if (!useBackdrop) {
return DWMSBT_AUTO;
}
return IsPopup() ? DWMSBT_TRANSIENTWINDOW : DWMSBT_TABBEDWINDOW;
@@ -2546,7 +2558,7 @@ void nsWindow::SetMicaBackdrop(bool aEnabled) {
// otherwise it'd draw the inactive window backdrop rather than
// acrylic). See also the WM_NCACTIVATE implementation.
const DWM_WINDOW_CORNER_PREFERENCE corner =
aEnabled ? DWMWCP_ROUND : DWMWCP_DEFAULT;
useBackdrop ? DWMWCP_ROUND : DWMWCP_DEFAULT;
::DwmSetWindowAttribute(mWnd, DWMWA_WINDOW_CORNER_PREFERENCE, &corner,
sizeof corner);
::PostMessageW(mWnd, WM_NCACTIVATE, TRUE, -1);

View File

@@ -340,6 +340,8 @@ class nsWindow final : public nsBaseWidget {
void SetSmallIconNoData();
void SetBigIconNoData();
void UpdateMicaBackdrop(bool aForce = false);
static void SetIsRestoringSession(const bool aIsRestoringSession) {
sIsRestoringSession = aIsRestoringSession;
}
@@ -879,6 +881,9 @@ class nsWindow final : public nsBaseWidget {
// Whether we're a PIP window.
bool mPIPWindow : 1;
// Whether we are asked to render a mica backdrop.
bool mMicaBackdrop : 1;
int32_t mCachedHitTestResult = 0;
// The point in time at which the last paint completed. We use this to avoid