| /**************************************************************************** |
| ** |
| ** Copyright (C) 2016 The Qt Company Ltd. |
| ** Contact: https://www.qt.io/licensing/ |
| ** |
| ** This file is part of the plugins of the Qt Toolkit. |
| ** |
| ** $QT_BEGIN_LICENSE:LGPL$ |
| ** Commercial License Usage |
| ** Licensees holding valid commercial Qt licenses may use this file in |
| ** accordance with the commercial license agreement provided with the |
| ** Software or, alternatively, in accordance with the terms contained in |
| ** a written agreement between you and The Qt Company. For licensing terms |
| ** and conditions see https://www.qt.io/terms-conditions. For further |
| ** information use the contact form at https://www.qt.io/contact-us. |
| ** |
| ** GNU Lesser General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU Lesser |
| ** General Public License version 3 as published by the Free Software |
| ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
| ** packaging of this file. Please review the following information to |
| ** ensure the GNU Lesser General Public License version 3 requirements |
| ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
| ** |
| ** GNU General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU |
| ** General Public License version 2.0 or (at your option) the GNU General |
| ** Public license version 3 or any later version approved by the KDE Free |
| ** Qt Foundation. The licenses are as published by the Free Software |
| ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
| ** included in the packaging of this file. Please review the following |
| ** information to ensure the GNU General Public License requirements will |
| ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
| ** https://www.gnu.org/licenses/gpl-3.0.html. |
| ** |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| #include "qwinrttheme.h" |
| #include "qwinrtmessagedialoghelper.h" |
| #include "qwinrtfiledialoghelper.h" |
| |
| #include <QtCore/qfunctions_winrt.h> |
| #include <QtGui/QPalette> |
| |
| #include <QtFontDatabaseSupport/private/qwinrtfontdatabase_p.h> |
| |
| #include <wrl.h> |
| #include <windows.ui.h> |
| #include <windows.ui.viewmanagement.h> |
| #if _MSC_VER >= 1900 |
| #include <windows.foundation.metadata.h> |
| using namespace ABI::Windows::Foundation::Metadata; |
| #endif |
| |
| using namespace Microsoft::WRL; |
| using namespace Microsoft::WRL::Wrappers; |
| using namespace ABI::Windows::UI; |
| using namespace ABI::Windows::UI::ViewManagement; |
| |
| QT_BEGIN_NAMESPACE |
| |
| Q_LOGGING_CATEGORY(lcQpaTheme, "qt.qpa.theme") |
| |
| class QWinRTApiInformationHandler { |
| public: |
| QWinRTApiInformationHandler() |
| { |
| HRESULT hr; |
| hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Foundation_Metadata_ApiInformation).Get(), |
| IID_PPV_ARGS(&m_apiInformationStatics)); |
| Q_ASSERT_SUCCEEDED(hr); |
| } |
| |
| ComPtr<IApiInformationStatics> apiInformationStatics() const |
| { |
| return m_apiInformationStatics; |
| } |
| |
| private: |
| ComPtr<IApiInformationStatics> m_apiInformationStatics; |
| }; |
| Q_GLOBAL_STATIC(QWinRTApiInformationHandler, gApiHandler); |
| |
| static IUISettings *uiSettings() |
| { |
| static ComPtr<IUISettings> settings; |
| if (!settings) { |
| HRESULT hr; |
| hr = RoActivateInstance(Wrappers::HString::MakeReference(RuntimeClass_Windows_UI_ViewManagement_UISettings).Get(), |
| &settings); |
| Q_ASSERT_SUCCEEDED(hr); |
| } |
| return settings.Get(); |
| } |
| |
| class QWinRTThemePrivate |
| { |
| public: |
| QWinRTThemePrivate() |
| : monospaceFont(QWinRTFontDatabase::familyForStyleHint(QFont::Monospace)) |
| { |
| } |
| |
| QPalette palette; |
| QFont monospaceFont; |
| }; |
| |
| static inline QColor fromColor(const Color &color) |
| { |
| return QColor(color.R, color.G, color.B, color.A); |
| } |
| |
| static bool uiColorSettings(const wchar_t *value, UIElementType type, Color *color) |
| { |
| ComPtr<IApiInformationStatics> apiInformationStatics = gApiHandler->apiInformationStatics(); |
| if (!apiInformationStatics) { |
| qErrnoWarning("Could not get ApiInformationStatics"); |
| return false; |
| } |
| |
| static const HStringReference enumRef(L"Windows.UI.ViewManagement.UIElementType"); |
| HStringReference valueRef(value); |
| |
| HRESULT hr; |
| boolean exists; |
| hr = apiInformationStatics->IsEnumNamedValuePresent(enumRef.Get(), valueRef.Get(), &exists); |
| |
| if (hr != S_OK || !exists) |
| return false; |
| |
| return SUCCEEDED(uiSettings()->UIElementColor(type, color)); |
| } |
| |
| static void nativeColorSettings(QPalette &p) |
| { |
| Color color; |
| |
| if (uiColorSettings(L"ActiveCaption", UIElementType_ActiveCaption, &color)) |
| p.setColor(QPalette::ToolTipBase, fromColor(color)); |
| |
| if (uiColorSettings(L"Background", UIElementType_Background, &color)) |
| p.setColor(QPalette::AlternateBase, fromColor(color)); |
| |
| if (uiColorSettings(L"ButtonFace", UIElementType_ButtonFace, &color)) { |
| p.setColor(QPalette::Button, fromColor(color)); |
| p.setColor(QPalette::Midlight, fromColor(color).lighter(110)); |
| p.setColor(QPalette::Light, fromColor(color).lighter(150)); |
| p.setColor(QPalette::Mid, fromColor(color).dark(130)); |
| p.setColor(QPalette::Dark, fromColor(color).dark(150)); |
| } |
| |
| if (uiColorSettings(L"ButtonText", UIElementType_ButtonText, &color)) { |
| p.setColor(QPalette::ButtonText, fromColor(color)); |
| p.setColor(QPalette::Text, fromColor(color)); |
| } |
| |
| if (uiColorSettings(L"CaptionText", UIElementType_CaptionText, &color)) |
| p.setColor(QPalette::ToolTipText, fromColor(color)); |
| |
| if (uiColorSettings(L"Highlight", UIElementType_Highlight, &color)) |
| p.setColor(QPalette::Highlight, fromColor(color)); |
| |
| if (uiColorSettings(L"HighlightText", UIElementType_HighlightText, &color)) |
| p.setColor(QPalette::HighlightedText, fromColor(color)); |
| |
| if (uiColorSettings(L"Window", UIElementType_Window, &color)) { |
| p.setColor(QPalette::Window, fromColor(color)); |
| p.setColor(QPalette::Base, fromColor(color)); |
| } |
| |
| if (uiColorSettings(L"Hotlight", UIElementType_Hotlight, &color)) |
| p.setColor(QPalette::BrightText, fromColor(color)); |
| |
| // Starting with SDK 15063 those have been removed. |
| #ifndef QT_WINRT_DISABLE_PHONE_COLORS |
| //Phone related |
| ComPtr<IApiInformationStatics> apiInformationStatics = gApiHandler->apiInformationStatics(); |
| boolean phoneApiPresent = false; |
| HRESULT hr; |
| HStringReference phoneRef(L"Windows.Phone.PhoneContract"); |
| hr = apiInformationStatics.Get()->IsApiContractPresentByMajor(phoneRef.Get(), 1, &phoneApiPresent); |
| if (FAILED(hr) || !phoneApiPresent) |
| return; |
| |
| if (uiColorSettings(L"PopupBackground", UIElementType_PopupBackground, &color)) { |
| p.setColor(QPalette::ToolTipBase, fromColor(color)); |
| p.setColor(QPalette::AlternateBase, fromColor(color)); |
| } |
| |
| if (uiColorSettings(L"NonTextMedium", UIElementType_NonTextMedium, &color)) |
| p.setColor(QPalette::Button, fromColor(color)); |
| |
| if (uiColorSettings(L"NonTextMediumHigh", UIElementType_NonTextMediumHigh, &color)) |
| p.setColor(QPalette::Midlight, fromColor(color)); |
| |
| if (uiColorSettings(L"NonTextHigh", UIElementType_NonTextHigh, &color)) |
| p.setColor(QPalette::Light, fromColor(color)); |
| |
| if (uiColorSettings(L"NonTextMediumLow", UIElementType_NonTextMediumLow, &color)) |
| p.setColor(QPalette::Mid, fromColor(color)); |
| |
| if (uiColorSettings(L"NonTextLow", UIElementType_NonTextLow, &color)) |
| p.setColor(QPalette::Dark, fromColor(color)); |
| |
| if (uiColorSettings(L"TextHigh", UIElementType_TextHigh, &color)) { |
| p.setColor(QPalette::ButtonText, fromColor(color)); |
| p.setColor(QPalette::Text, fromColor(color)); |
| p.setColor(QPalette::WindowText, fromColor(color)); |
| } |
| |
| if (uiColorSettings(L"TextMedium", UIElementType_TextMedium, &color)) |
| p.setColor(QPalette::ToolTipText, fromColor(color)); |
| |
| if (uiColorSettings(L"AccentColor", UIElementType_AccentColor, &color)) |
| p.setColor(QPalette::Highlight, fromColor(color)); |
| |
| if (uiColorSettings(L"PageBackground", UIElementType_PageBackground, &color)) { |
| p.setColor(QPalette::Window, fromColor(color)); |
| p.setColor(QPalette::Base, fromColor(color)); |
| } |
| |
| if (uiColorSettings(L"TextContrastWithHigh", UIElementType_TextContrastWithHigh, &color)) |
| p.setColor(QPalette::BrightText, fromColor(color)); |
| #endif // QT_WINRT_DISABLE_PHONE_COLORS |
| } |
| |
| QWinRTTheme::QWinRTTheme() |
| : d_ptr(new QWinRTThemePrivate) |
| { |
| Q_D(QWinRTTheme); |
| qCDebug(lcQpaTheme) << __FUNCTION__; |
| |
| nativeColorSettings(d->palette); |
| } |
| |
| bool QWinRTTheme::usePlatformNativeDialog(DialogType type) const |
| { |
| qCDebug(lcQpaTheme) << __FUNCTION__ << type; |
| static bool useNativeDialogs = qEnvironmentVariableIsSet("QT_USE_WINRT_NATIVE_DIALOGS") |
| ? qEnvironmentVariableIntValue("QT_USE_WINRT_NATIVE_DIALOGS") : true; |
| |
| if (type == FileDialog || type == MessageDialog) |
| return useNativeDialogs; |
| return false; |
| } |
| |
| QPlatformDialogHelper *QWinRTTheme::createPlatformDialogHelper(DialogType type) const |
| { |
| qCDebug(lcQpaTheme) << __FUNCTION__ << type; |
| switch (type) { |
| case FileDialog: |
| return new QWinRTFileDialogHelper; |
| case MessageDialog: |
| return new QWinRTMessageDialogHelper(this); |
| default: |
| break; |
| } |
| return QPlatformTheme::createPlatformDialogHelper(type); |
| } |
| |
| QVariant QWinRTTheme::styleHint(QPlatformIntegration::StyleHint hint) |
| { |
| qCDebug(lcQpaTheme) << __FUNCTION__ << hint; |
| HRESULT hr; |
| switch (hint) { |
| case QPlatformIntegration::CursorFlashTime: { |
| quint32 blinkRate; |
| hr = uiSettings()->get_CaretBlinkRate(&blinkRate); |
| RETURN_IF_FAILED("Failed to get caret blink rate", return defaultThemeHint(CursorFlashTime)); |
| return blinkRate; |
| } |
| case QPlatformIntegration::KeyboardInputInterval: |
| return defaultThemeHint(KeyboardInputInterval); |
| case QPlatformIntegration::MouseDoubleClickInterval: { |
| quint32 doubleClickTime; |
| hr = uiSettings()->get_DoubleClickTime(&doubleClickTime); |
| RETURN_IF_FAILED("Failed to get double click time", return defaultThemeHint(MouseDoubleClickInterval)); |
| return doubleClickTime; |
| } |
| case QPlatformIntegration::StartDragDistance: |
| return defaultThemeHint(StartDragDistance); |
| case QPlatformIntegration::StartDragTime: |
| return defaultThemeHint(StartDragTime); |
| case QPlatformIntegration::KeyboardAutoRepeatRate: |
| return defaultThemeHint(KeyboardAutoRepeatRate); |
| case QPlatformIntegration::ShowIsFullScreen: |
| return false; |
| case QPlatformIntegration::PasswordMaskDelay: |
| return defaultThemeHint(PasswordMaskDelay); |
| case QPlatformIntegration::FontSmoothingGamma: |
| return qreal(1.7); |
| case QPlatformIntegration::StartDragVelocity: |
| return defaultThemeHint(StartDragVelocity); |
| case QPlatformIntegration::UseRtlExtensions: |
| return false; |
| case QPlatformIntegration::PasswordMaskCharacter: |
| return defaultThemeHint(PasswordMaskCharacter); |
| case QPlatformIntegration::SetFocusOnTouchRelease: |
| return true; |
| case QPlatformIntegration::ShowIsMaximized: |
| return true; |
| case QPlatformIntegration::MousePressAndHoldInterval: |
| return defaultThemeHint(MousePressAndHoldInterval); |
| default: |
| break; |
| } |
| return QVariant(); |
| } |
| |
| QVariant QWinRTTheme::themeHint(ThemeHint hint) const |
| { |
| qCDebug(lcQpaTheme) << __FUNCTION__ << hint; |
| switch (hint) { |
| case StyleNames: |
| return QStringList() << QStringLiteral("fusion") << QStringLiteral("windows"); |
| default: |
| return QPlatformTheme::themeHint(hint); |
| } |
| } |
| |
| const QPalette *QWinRTTheme::palette(Palette type) const |
| { |
| Q_D(const QWinRTTheme); |
| qCDebug(lcQpaTheme) << __FUNCTION__ << type; |
| if (type == SystemPalette) |
| return &d->palette; |
| return QPlatformTheme::palette(type); |
| } |
| |
| const QFont *QWinRTTheme::font(QPlatformTheme::Font type) const |
| { |
| Q_D(const QWinRTTheme); |
| qCDebug(lcQpaTheme) << __FUNCTION__ << type; |
| if (type == QPlatformTheme::FixedFont) |
| return &d->monospaceFont; |
| |
| return QPlatformTheme::font(type); |
| } |
| |
| QT_END_NAMESPACE |