diff options
author | Piotr Wiercinski <[email protected]> | 2025-03-05 21:09:59 +0100 |
---|---|---|
committer | Piotr Wiercinski <[email protected]> | 2025-04-04 13:52:53 +0200 |
commit | 8f65024d848144c716a4a6522180a36c518b2e3a (patch) | |
tree | 1322872f5bcc9934cd4f2940839ed96c65a82c4c | |
parent | 9302945ce35c836f97f50ac78bfb74b45824ca59 (diff) |
wasm: Add support for contrastPreference detection to WASM theme
Task-number: QTBUG-133596
Change-Id: I4482fe5a3457579867bd870cb2c8d371dd08e1a0
Reviewed-by: Oliver Eftevaag <[email protected]>
-rw-r--r-- | src/plugins/platforms/wasm/qwasmtheme.cpp | 106 | ||||
-rw-r--r-- | src/plugins/platforms/wasm/qwasmtheme.h | 38 |
2 files changed, 102 insertions, 42 deletions
diff --git a/src/plugins/platforms/wasm/qwasmtheme.cpp b/src/plugins/platforms/wasm/qwasmtheme.cpp index 37abb309bff..b9340f31275 100644 --- a/src/plugins/platforms/wasm/qwasmtheme.cpp +++ b/src/plugins/platforms/wasm/qwasmtheme.cpp @@ -5,32 +5,55 @@ #include <QtCore/qvariant.h> #include <QFontDatabase> #include <QList> +#include <qloggingcategory.h> #include <qpa/qwindowsysteminterface.h> #include <qpalette.h> -#include <private/qstdweb_p.h> - #include <emscripten.h> #include <emscripten/bind.h> #include <emscripten/val.h> Q_GUI_EXPORT QPalette qt_fusionPalette(); -Qt::ColorScheme QWasmTheme::s_autoColorScheme = Qt::ColorScheme::Unknown; -bool QWasmTheme::s_autoPaletteIsDirty = false; - QT_BEGIN_NAMESPACE +Q_STATIC_LOGGING_CATEGORY(lcQpaThemeWasm, "qt.qpa.theme.wasm") + +namespace { +bool matchMedia(std::string mediaQueryString) +{ + return emscripten::val::global("window") + .call<emscripten::val>("matchMedia", mediaQueryString)["matches"] + .as<bool>(); +} + +Qt::ColorScheme getColorSchemeFromMedia() +{ + if (matchMedia(colorSchemePreferenceDark)) { + return Qt::ColorScheme::Dark; + } else { + return Qt::ColorScheme::Light; + } +} + +Qt::ContrastPreference getContrastPreferenceFromMedia() +{ + if (matchMedia(contrastPreferenceMore)) { + return Qt::ContrastPreference::HighContrast; + } else { + return Qt::ContrastPreference::NoPreference; + } +} +} // namespace + using namespace Qt::StringLiterals; QWasmTheme::QWasmTheme() { - if (emscripten::val::global("window").call<emscripten::val>( - "matchMedia", - std::string("(prefers-color-scheme:dark)"))["matches"].as<bool>()) - s_autoColorScheme = Qt::ColorScheme::Dark; - else - s_autoColorScheme = Qt::ColorScheme::Light; + m_colorScheme = getColorSchemeFromMedia(); + qCDebug(lcQpaThemeWasm) << "Initializing Wasm theme. Color scheme: " << m_colorScheme; + m_contrastPreference = getContrastPreferenceFromMedia(); + qCDebug(lcQpaThemeWasm) << "Initializing Wasm theme. Contrast preference: " << m_contrastPreference; for (auto family : QFontDatabase::families()) if (QFontDatabase::isFixedPitch(family)) @@ -39,15 +62,15 @@ QWasmTheme::QWasmTheme() m_palette = std::make_unique<QPalette>(); m_paletteIsDirty = true; // Force update later - const auto callback = [=](emscripten::val event) { QWasmTheme::onColorSchemeChange(event); }; - const emscripten::val window = emscripten::val::global("window"); - if (!window.isUndefined()) { - const emscripten::val matchMedia = window.call<emscripten::val>("matchMedia", emscripten::val("(prefers-color-scheme: dark)")); - if (!matchMedia.isUndefined()) { - static auto changeEvent = - std::make_unique<qstdweb::EventCallback>(matchMedia, "change", callback); - } - } + registerCallbacks( + { colorSchemePreferenceDark }, + [this](emscripten::val) { QWasmTheme::onColorSchemeChange(); }, + m_colorSchemeChangeCallback); + registerCallbacks( + { contrastPreferenceNoPreference, contrastPreferenceMore, contrastPreferenceLess, + contrastPreferenceCustom }, + [this](emscripten::val) { QWasmTheme::onContrastPreferenceChange(); }, + m_contrastPreferenceChangeCallbacks); } QWasmTheme::~QWasmTheme() @@ -59,9 +82,8 @@ QWasmTheme::~QWasmTheme() const QPalette *QWasmTheme::palette(Palette type) const { if (type == SystemPalette) { - if (m_paletteIsDirty || s_autoPaletteIsDirty) { + if (m_paletteIsDirty) { m_paletteIsDirty = false; - s_autoPaletteIsDirty = false; *m_palette = qt_fusionPalette(); } return m_palette.get(); @@ -71,9 +93,7 @@ const QPalette *QWasmTheme::palette(Palette type) const Qt::ColorScheme QWasmTheme::colorScheme() const { - if (m_colorScheme != Qt::ColorScheme::Unknown) - return m_colorScheme; - return s_autoColorScheme; + return m_colorScheme; } void QWasmTheme::requestColorScheme(Qt::ColorScheme scheme) @@ -85,6 +105,11 @@ void QWasmTheme::requestColorScheme(Qt::ColorScheme scheme) } } +Qt::ContrastPreference QWasmTheme::contrastPreference() const +{ + return m_contrastPreference; +} + QVariant QWasmTheme::themeHint(ThemeHint hint) const { if (hint == QPlatformTheme::StyleNames) @@ -102,20 +127,25 @@ const QFont *QWasmTheme::font(Font type) const return nullptr; } -void QWasmTheme::onColorSchemeChange(emscripten::val event) +void QWasmTheme::onColorSchemeChange() { - const emscripten::val matches = event["matches"]; - if (!matches.isUndefined()) { - const auto oldAutoColorScheme = s_autoColorScheme; - if (matches.as<int>()) - s_autoColorScheme = Qt::ColorScheme::Dark; - else - s_autoColorScheme = Qt::ColorScheme::Light; - - if (oldAutoColorScheme != s_autoColorScheme) { - s_autoPaletteIsDirty = true; - QWindowSystemInterface::handleThemeChange<QWindowSystemInterface::SynchronousDelivery>(); - } + auto colorScheme = getColorSchemeFromMedia(); + if (m_colorScheme != colorScheme) { + qCDebug(lcQpaThemeWasm) << "Color scheme changed to " << colorScheme; + m_colorScheme = colorScheme; + m_paletteIsDirty = true; + QWindowSystemInterface::handleThemeChange<QWindowSystemInterface::SynchronousDelivery>(); + } +} + +void QWasmTheme::onContrastPreferenceChange() +{ + auto contrastPreference = getContrastPreferenceFromMedia(); + if (m_contrastPreference != contrastPreference) { + qCDebug(lcQpaThemeWasm) << "Contrast preference changed to " << contrastPreference; + m_contrastPreference = contrastPreference; + m_paletteIsDirty = true; + QWindowSystemInterface::handleThemeChange<QWindowSystemInterface::SynchronousDelivery>(); } } diff --git a/src/plugins/platforms/wasm/qwasmtheme.h b/src/plugins/platforms/wasm/qwasmtheme.h index dce1632a5e3..4eaad874c76 100644 --- a/src/plugins/platforms/wasm/qwasmtheme.h +++ b/src/plugins/platforms/wasm/qwasmtheme.h @@ -7,6 +7,10 @@ #include <qpa/qplatformtheme.h> #include <QtGui/QFont> +#include <memory> + +#include <private/qstdweb_p.h> + QT_BEGIN_NAMESPACE class QWasmEventTranslator; @@ -17,6 +21,30 @@ class QWasmScreen; class QWasmCompositor; class QWasmBackingStore; +// this reflects @media/prefers-contrast +constexpr auto colorSchemePreferenceDark = "(prefers-color-scheme: dark)"; +constexpr auto contrastPreferenceNoPreference = "(prefers-contrast: no-preference)"; +constexpr auto contrastPreferenceMore = "(prefers-contrast: more)"; +constexpr auto contrastPreferenceLess = "(prefers-contrast: less)"; +constexpr auto contrastPreferenceCustom = "(prefers-contrast: custom)"; + +template <typename MediaName, typename CallbackFn, typename Container> +void registerCallbacks(std::initializer_list<MediaName> mediaNames, CallbackFn callback, Container &callbacksContainer) +{ + emscripten::val window = emscripten::val::global("window"); + if (!window.isUndefined()) { + for (auto &&mediaName : mediaNames) { + auto media = window.call<emscripten::val>("matchMedia", emscripten::val(mediaName)); + if constexpr (std::is_same_v<Container, std::vector<QWasmEventHandler>>) { + callbacksContainer.emplace_back(media, "change", callback); + } else { + Q_ASSERT(mediaNames.size() == 1); + callbacksContainer = QWasmEventHandler(media, "change", callback); + } + } + } +} + class QWasmTheme : public QPlatformTheme { public: @@ -26,19 +54,21 @@ public: const QPalette *palette(Palette type = SystemPalette) const override; Qt::ColorScheme colorScheme() const override; void requestColorScheme(Qt::ColorScheme scheme) override; + Qt::ContrastPreference contrastPreference() const override; QVariant themeHint(ThemeHint hint) const override; const QFont *font(Font type) const override; QFont *fixedFont = nullptr; - static void onColorSchemeChange(emscripten::val event); + void onColorSchemeChange(); + void onContrastPreferenceChange(); private: Qt::ColorScheme m_colorScheme = Qt::ColorScheme::Unknown; + QWasmEventHandler m_colorSchemeChangeCallback; std::unique_ptr<QPalette> m_palette; mutable bool m_paletteIsDirty = false; - - static Qt::ColorScheme s_autoColorScheme; - static bool s_autoPaletteIsDirty; + Qt::ContrastPreference m_contrastPreference; + std::vector<QWasmEventHandler> m_contrastPreferenceChangeCallbacks; }; QT_END_NAMESPACE |