blob: 0e1504b1c1a7a1c06f5f9f9915191c42d425f287 [file] [log] [blame]
/****************************************************************************
**
** 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