/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "WinContentSystemParameters.h" #include "WinUtils.h" #include "nsUXThemeData.h" #include "mozilla/Mutex.h" #include "mozilla/dom/ContentChild.h" #include "mozilla/dom/ContentParent.h" namespace mozilla { namespace widget { using dom::SystemParameterKVPair; static_assert(uint8_t(SystemParameterId::Count) < 32, "Too many SystemParameterId for " "WinContentSystemParameters::Detail::validCachedValueBitfield"); struct WinContentSystemParameters::Detail { OffTheBooksMutex mutex{"WinContentSystemParameters::Detail::mutex"}; // A bitfield indicating which cached ids are valid uint32_t validCachedValueBitfield{0}; bool cachedIsPerMonitorDPIAware{false}; float cachedSystemDPI{0.0f}; bool cachedFlatMenusEnabled{false}; // Almost-always true in Windows 7, always true starting in Windows 8 bool cachedIsAppThemed{true}; }; // static WinContentSystemParameters* WinContentSystemParameters::GetSingleton() { static WinContentSystemParameters sInstance{}; return &sInstance; } WinContentSystemParameters::WinContentSystemParameters() : mDetail(std::make_unique()) {} WinContentSystemParameters::~WinContentSystemParameters() {} bool WinContentSystemParameters::IsPerMonitorDPIAware() { MOZ_ASSERT(XRE_IsContentProcess()); OffTheBooksMutexAutoLock lock(mDetail->mutex); MOZ_RELEASE_ASSERT( IsCachedValueValid(SystemParameterId::IsPerMonitorDPIAware)); return mDetail->cachedIsPerMonitorDPIAware; } float WinContentSystemParameters::SystemDPI() { MOZ_ASSERT(XRE_IsContentProcess()); OffTheBooksMutexAutoLock lock(mDetail->mutex); MOZ_RELEASE_ASSERT(IsCachedValueValid(SystemParameterId::SystemDPI)); return mDetail->cachedSystemDPI; } bool WinContentSystemParameters::AreFlatMenusEnabled() { MOZ_ASSERT(XRE_IsContentProcess()); OffTheBooksMutexAutoLock lock(mDetail->mutex); MOZ_RELEASE_ASSERT(IsCachedValueValid(SystemParameterId::FlatMenusEnabled)); return mDetail->cachedFlatMenusEnabled; } bool WinContentSystemParameters::IsAppThemed() { MOZ_ASSERT(XRE_IsContentProcess()); OffTheBooksMutexAutoLock lock(mDetail->mutex); MOZ_RELEASE_ASSERT(IsCachedValueValid(SystemParameterId::IsAppThemed)); return mDetail->cachedIsAppThemed; } void WinContentSystemParameters::SetContentValueInternal( const SystemParameterKVPair& aKVPair) { MOZ_ASSERT(XRE_IsContentProcess()); MOZ_ASSERT(NS_IsMainThread()); MOZ_RELEASE_ASSERT(aKVPair.id() < uint8_t(SystemParameterId::Count)); SetCachedValueValid(SystemParameterId(aKVPair.id()), true); mDetail->mutex.AssertCurrentThreadOwns(); switch (SystemParameterId(aKVPair.id())) { case SystemParameterId::IsPerMonitorDPIAware: mDetail->cachedIsPerMonitorDPIAware = aKVPair.value(); return; case SystemParameterId::SystemDPI: mDetail->cachedSystemDPI = aKVPair.value(); return; case SystemParameterId::FlatMenusEnabled: mDetail->cachedFlatMenusEnabled = aKVPair.value(); return; case SystemParameterId::IsAppThemed: mDetail->cachedIsAppThemed = aKVPair.value(); return; case SystemParameterId::Count: MOZ_CRASH("Invalid SystemParameterId"); } MOZ_CRASH("Unhandled SystemParameterId"); } void WinContentSystemParameters::SetContentValues( const nsTArray& values) { MOZ_ASSERT(XRE_IsContentProcess()); MOZ_ASSERT(NS_IsMainThread()); OffTheBooksMutexAutoLock lock(mDetail->mutex); for (auto& kvPair : values) { SetContentValueInternal(kvPair); } } bool WinContentSystemParameters::GetParentValueInternal( SystemParameterId aId, SystemParameterKVPair* aKVPair) { MOZ_ASSERT(XRE_IsParentProcess()); MOZ_ASSERT(aKVPair); aKVPair->id() = uint8_t(aId); switch (aId) { case SystemParameterId::IsPerMonitorDPIAware: aKVPair->value() = WinUtils::IsPerMonitorDPIAware(); return true; case SystemParameterId::SystemDPI: aKVPair->value() = WinUtils::SystemDPI(); return true; case SystemParameterId::FlatMenusEnabled: aKVPair->value() = nsUXThemeData::AreFlatMenusEnabled(); return true; case SystemParameterId::IsAppThemed: aKVPair->value() = nsUXThemeData::IsAppThemed(); return true; case SystemParameterId::Count: MOZ_CRASH("Invalid SystemParameterId"); } MOZ_CRASH("Unhandled SystemParameterId"); } nsTArray WinContentSystemParameters::GetParentValues() { MOZ_ASSERT(XRE_IsParentProcess()); nsTArray results; for (uint8_t i = 0; i < uint8_t(SystemParameterId::Count); ++i) { dom::SystemParameterKVPair kvPair{}; GetParentValueInternal(SystemParameterId(i), &kvPair); results.AppendElement(std::move(kvPair)); } return results; } void WinContentSystemParameters::OnThemeChanged() { MOZ_ASSERT(XRE_IsParentProcess()); nsTArray updates; { dom::SystemParameterKVPair kvPair{}; GetParentValueInternal(SystemParameterId::FlatMenusEnabled, &kvPair); updates.AppendElement(std::move(kvPair)); } { dom::SystemParameterKVPair kvPair{}; GetParentValueInternal(SystemParameterId::IsAppThemed, &kvPair); updates.AppendElement(std::move(kvPair)); } nsTArray contentProcesses{}; dom::ContentParent::GetAll(contentProcesses); for (auto contentProcess : contentProcesses) { Unused << contentProcess->SendUpdateSystemParameters(updates); } } bool WinContentSystemParameters::IsCachedValueValid(SystemParameterId aId) { MOZ_ASSERT(XRE_IsContentProcess()); MOZ_ASSERT(uint8_t(aId) < uint8_t(SystemParameterId::Count)); mDetail->mutex.AssertCurrentThreadOwns(); uint32_t mask = uint32_t(1) << uint8_t(aId); return (mDetail->validCachedValueBitfield & mask) != 0; } void WinContentSystemParameters::SetCachedValueValid(SystemParameterId aId, bool aIsValid) { MOZ_ASSERT(XRE_IsContentProcess()); MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(uint8_t(aId) < uint8_t(SystemParameterId::Count)); mDetail->mutex.AssertCurrentThreadOwns(); uint32_t mask = uint32_t(1) << uint8_t(aId); if (aIsValid) { mDetail->validCachedValueBitfield |= mask; } else { mDetail->validCachedValueBitfield &= ~mask; } } } // namespace widget } // namespace mozilla