1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the plugins of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qwindowstheme.h"
43 #include "qwindowsdialoghelpers.h"
44 #include "qwindowscontext.h"
45 #include "qwindowsintegration.h"
46 #include "qt_windows.h"
47 #include "qwindowsfontdatabase.h"
49 # include "qplatformfunctions_wince.h"
53 #include <QtCore/QVariant>
54 #include <QtCore/QCoreApplication>
55 #include <QtCore/QDebug>
56 #include <QtCore/QTextStream>
57 #include <QtCore/QSysInfo>
58 #include <QtGui/QPalette>
59 #include <QtGui/QGuiApplication>
60 #include <qpa/qwindowsysteminterface.h>
64 static inline QTextStream& operator<<(QTextStream &str, const QColor &c)
66 str.setIntegerBase(16);
68 str.setPadChar(QLatin1Char('0'));
69 str << " rgb: #" << c.red() << c.green() << c.blue();
70 str.setIntegerBase(10);
75 static inline void paletteRoleToString(const QPalette &palette,
76 const QPalette::ColorRole role,
81 str.setPadChar(QLatin1Char('0'));
84 str << " Active: " << palette.color(QPalette::Active, role)
85 << " Disabled: " << palette.color(QPalette::Disabled, role)
86 << " Inactive: " << palette.color(QPalette::Inactive, role)
90 static inline QString paletteToString(const QPalette &palette)
93 QTextStream str(&result);
94 for (int r = 0; r < QPalette::NColorRoles; ++r)
95 paletteRoleToString(palette, static_cast<QPalette::ColorRole>(r), str);
99 static inline bool booleanSystemParametersInfo(UINT what, bool defaultValue)
102 if (SystemParametersInfo(what, 0, &result, 0))
103 return result ? true : false;
107 static inline bool dWordSystemParametersInfo(UINT what, DWORD defaultValue)
110 if (SystemParametersInfo(what, 0, &result, 0))
115 static inline QColor mixColors(const QColor &c1, const QColor &c2)
117 return QColor ((c1.red() + c2.red()) / 2,
118 (c1.green() + c2.green()) / 2,
119 (c1.blue() + c2.blue()) / 2);
122 static inline QColor getSysColor(int index)
124 return qColorToCOLORREF(GetSysColor(index));
127 // from QStyle::standardPalette
128 static inline QPalette standardPalette()
130 QColor backgroundColor(0xd4, 0xd0, 0xc8); // win 2000 grey
131 QColor lightColor(backgroundColor.lighter());
132 QColor darkColor(backgroundColor.darker());
133 const QBrush darkBrush(darkColor);
134 QColor midColor(Qt::gray);
135 QPalette palette(Qt::black, backgroundColor, lightColor, darkColor,
136 midColor, Qt::black, Qt::white);
137 palette.setBrush(QPalette::Disabled, QPalette::WindowText, darkBrush);
138 palette.setBrush(QPalette::Disabled, QPalette::Text, darkBrush);
139 palette.setBrush(QPalette::Disabled, QPalette::ButtonText, darkBrush);
140 palette.setBrush(QPalette::Disabled, QPalette::Base, QBrush(backgroundColor));
144 static inline QPalette systemPalette()
146 QPalette result = standardPalette();
147 result.setColor(QPalette::WindowText, getSysColor(COLOR_WINDOWTEXT));
148 result.setColor(QPalette::Button, getSysColor(COLOR_BTNFACE));
149 result.setColor(QPalette::Light, getSysColor(COLOR_BTNHIGHLIGHT));
150 result.setColor(QPalette::Dark, getSysColor(COLOR_BTNSHADOW));
151 result.setColor(QPalette::Mid, result.button().color().darker(150));
152 result.setColor(QPalette::Text, getSysColor(COLOR_WINDOWTEXT));
153 result.setColor(QPalette::BrightText, getSysColor(COLOR_BTNHIGHLIGHT));
154 result.setColor(QPalette::Base, getSysColor(COLOR_WINDOW));
155 result.setColor(QPalette::Window, getSysColor(COLOR_BTNFACE));
156 result.setColor(QPalette::ButtonText, getSysColor(COLOR_BTNTEXT));
157 result.setColor(QPalette::Midlight, getSysColor(COLOR_3DLIGHT));
158 result.setColor(QPalette::Shadow, getSysColor(COLOR_3DDKSHADOW));
159 result.setColor(QPalette::Highlight, getSysColor(COLOR_HIGHLIGHT));
160 result.setColor(QPalette::HighlightedText, getSysColor(COLOR_HIGHLIGHTTEXT));
161 result.setColor(QPalette::Link, Qt::blue);
162 result.setColor(QPalette::LinkVisited, Qt::magenta);
163 result.setColor(QPalette::Inactive, QPalette::Button, result.button().color());
164 result.setColor(QPalette::Inactive, QPalette::Window, result.background().color());
165 result.setColor(QPalette::Inactive, QPalette::Light, result.light().color());
166 result.setColor(QPalette::Inactive, QPalette::Dark, result.dark().color());
168 if (result.midlight() == result.button())
169 result.setColor(QPalette::Midlight, result.button().color().lighter(110));
170 if (result.background() != result.base()) {
171 result.setColor(QPalette::Inactive, QPalette::Highlight, result.color(QPalette::Inactive, QPalette::Window));
172 result.setColor(QPalette::Inactive, QPalette::HighlightedText, result.color(QPalette::Inactive, QPalette::Text));
175 const QColor disabled =
176 mixColors(result.foreground().color(), result.button().color());
178 result.setColorGroup(QPalette::Disabled, result.foreground(), result.button(),
179 result.light(), result.dark(), result.mid(),
180 result.text(), result.brightText(), result.base(),
181 result.background());
182 result.setColor(QPalette::Disabled, QPalette::WindowText, disabled);
183 result.setColor(QPalette::Disabled, QPalette::Text, disabled);
184 result.setColor(QPalette::Disabled, QPalette::ButtonText, disabled);
185 result.setColor(QPalette::Disabled, QPalette::Highlight,
186 getSysColor(COLOR_HIGHLIGHT));
187 result.setColor(QPalette::Disabled, QPalette::HighlightedText,
188 getSysColor(COLOR_HIGHLIGHTTEXT));
189 result.setColor(QPalette::Disabled, QPalette::Base,
190 result.background().color());
194 static inline QPalette toolTipPalette(const QPalette &systemPalette)
196 QPalette result(systemPalette);
197 const QColor tipBgColor(getSysColor(COLOR_INFOBK));
198 const QColor tipTextColor(getSysColor(COLOR_INFOTEXT));
200 result.setColor(QPalette::All, QPalette::Button, tipBgColor);
201 result.setColor(QPalette::All, QPalette::Window, tipBgColor);
202 result.setColor(QPalette::All, QPalette::Text, tipTextColor);
203 result.setColor(QPalette::All, QPalette::WindowText, tipTextColor);
204 result.setColor(QPalette::All, QPalette::ButtonText, tipTextColor);
205 result.setColor(QPalette::All, QPalette::Button, tipBgColor);
206 result.setColor(QPalette::All, QPalette::Window, tipBgColor);
207 result.setColor(QPalette::All, QPalette::Text, tipTextColor);
208 result.setColor(QPalette::All, QPalette::WindowText, tipTextColor);
209 result.setColor(QPalette::All, QPalette::ButtonText, tipTextColor);
210 const QColor disabled =
211 mixColors(result.foreground().color(), result.button().color());
212 result.setColor(QPalette::Disabled, QPalette::WindowText, disabled);
213 result.setColor(QPalette::Disabled, QPalette::Text, disabled);
214 result.setColor(QPalette::Disabled, QPalette::Base, Qt::white);
215 result.setColor(QPalette::Disabled, QPalette::BrightText, Qt::white);
219 static inline QPalette menuPalette(const QPalette &systemPalette)
221 QPalette result(systemPalette);
222 const QColor menuColor(getSysColor(COLOR_MENU));
223 const QColor menuTextColor(getSysColor(COLOR_MENUTEXT));
224 const QColor disabled(getSysColor(COLOR_GRAYTEXT));
225 const bool isFlat = booleanSystemParametersInfo(SPI_GETFLATMENU, false);
226 // we might need a special color group for the result.
227 result.setColor(QPalette::Active, QPalette::Button, menuColor);
228 result.setColor(QPalette::Active, QPalette::Text, menuTextColor);
229 result.setColor(QPalette::Active, QPalette::WindowText, menuTextColor);
230 result.setColor(QPalette::Active, QPalette::ButtonText, menuTextColor);
231 result.setColor(QPalette::Disabled, QPalette::WindowText, disabled);
232 result.setColor(QPalette::Disabled, QPalette::Text, disabled);
234 result.setColor(QPalette::Disabled, QPalette::Highlight,
235 getSysColor(isFlat ? COLOR_MENUHILIGHT : COLOR_HIGHLIGHT));
237 result.setColor(QPalette::Disabled, QPalette::Highlight,
238 getSysColor(COLOR_HIGHLIGHT));
240 result.setColor(QPalette::Disabled, QPalette::HighlightedText, disabled);
241 result.setColor(QPalette::Disabled, QPalette::Button,
242 result.color(QPalette::Active, QPalette::Button));
243 result.setColor(QPalette::Inactive, QPalette::Button,
244 result.color(QPalette::Active, QPalette::Button));
245 result.setColor(QPalette::Inactive, QPalette::Text,
246 result.color(QPalette::Active, QPalette::Text));
247 result.setColor(QPalette::Inactive, QPalette::WindowText,
248 result.color(QPalette::Active, QPalette::WindowText));
249 result.setColor(QPalette::Inactive, QPalette::ButtonText,
250 result.color(QPalette::Active, QPalette::ButtonText));
251 result.setColor(QPalette::Inactive, QPalette::Highlight,
252 result.color(QPalette::Active, QPalette::Highlight));
253 result.setColor(QPalette::Inactive, QPalette::HighlightedText,
254 result.color(QPalette::Active, QPalette::HighlightedText));
255 result.setColor(QPalette::Inactive, QPalette::ButtonText,
256 systemPalette.color(QPalette::Inactive, QPalette::Dark));
260 static inline QPalette *menuBarPalette(const QPalette &menuPalette)
262 QPalette *result = 0;
263 if (booleanSystemParametersInfo(SPI_GETFLATMENU, false)) {
264 result = new QPalette(menuPalette);
266 const QColor menubar(getSysColor(COLOR_MENUBAR));
268 const QColor menubar(getSysColor(COLOR_MENU));
270 result->setColor(QPalette::Active, QPalette::Button, menubar);
271 result->setColor(QPalette::Disabled, QPalette::Button, menubar);
272 result->setColor(QPalette::Inactive, QPalette::Button, menubar);
277 const char *QWindowsTheme::name = "windows";
278 QWindowsTheme *QWindowsTheme::m_instance = 0;
280 QWindowsTheme::QWindowsTheme()
283 qFill(m_fonts, m_fonts + NFonts, static_cast<QFont *>(0));
284 qFill(m_palettes, m_palettes + NPalettes, static_cast<QPalette *>(0));
288 QWindowsTheme::~QWindowsTheme()
295 static inline QStringList iconThemeSearchPaths()
297 const QFileInfo appDir(QCoreApplication::applicationDirPath() + QStringLiteral("/icons"));
298 return appDir.isDir() ? QStringList(appDir.absoluteFilePath()) : QStringList();
301 static inline QStringList styleNames()
304 if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA)
305 result.append(QStringLiteral("WindowsVista"));
306 if (QSysInfo::WindowsVersion >= QSysInfo::WV_XP)
307 result.append(QStringLiteral("WindowsXP"));
308 result.append(QStringLiteral("Windows"));
312 static inline int uiEffects()
315 if (booleanSystemParametersInfo(SPI_GETUIEFFECTS, false))
316 result |= QPlatformTheme::GeneralUiEffect;
317 if (booleanSystemParametersInfo(SPI_GETMENUANIMATION, false))
318 result |= QPlatformTheme::AnimateMenuUiEffect;
319 if (booleanSystemParametersInfo(SPI_GETMENUFADE, false))
320 result |= QPlatformTheme::FadeMenuUiEffect;
321 if (booleanSystemParametersInfo(SPI_GETCOMBOBOXANIMATION, false))
322 result |= QPlatformTheme::AnimateComboUiEffect;
323 if (booleanSystemParametersInfo(SPI_GETTOOLTIPANIMATION, false))
324 result |= QPlatformTheme::AnimateTooltipUiEffect;
328 QVariant QWindowsTheme::themeHint(ThemeHint hint) const
331 case UseFullScreenForPopupMenu:
332 return QVariant(true);
333 case DialogButtonBoxLayout:
334 return QVariant(int(0)); // QDialogButtonBox::WinLayout
335 case IconThemeSearchPaths:
336 return QVariant(iconThemeSearchPaths());
338 return QVariant(styleNames());
340 case TextCursorWidth:
341 return QVariant(int(dWordSystemParametersInfo(SPI_GETCARETWIDTH, 1u)));
343 return QVariant(booleanSystemParametersInfo(SPI_GETDROPSHADOW, false));
344 #endif // !Q_OS_WINCE
345 case MaximumScrollBarDragDistance:
346 return QVariant(qRound(qreal(QWindowsContext::instance()->defaultDPI()) * 1.375));
348 return QVariant(int(WindowsKeyboardScheme));
350 return QVariant(uiEffects());
354 return QPlatformTheme::themeHint(hint);
357 void QWindowsTheme::clearPalettes()
359 qDeleteAll(m_palettes, m_palettes + NPalettes);
360 qFill(m_palettes, m_palettes + NPalettes, static_cast<QPalette *>(0));
363 void QWindowsTheme::refreshPalettes()
366 if (!QGuiApplication::desktopSettingsAware())
368 m_palettes[SystemPalette] = new QPalette(systemPalette());
369 m_palettes[ToolTipPalette] = new QPalette(toolTipPalette(*m_palettes[SystemPalette]));
370 m_palettes[MenuPalette] = new QPalette(menuPalette(*m_palettes[SystemPalette]));
371 m_palettes[MenuBarPalette] = menuBarPalette(*m_palettes[MenuPalette]);
372 if (QWindowsContext::verboseTheming)
373 qDebug() << __FUNCTION__ << '\n'
374 << " system=" << paletteToString(*m_palettes[SystemPalette])
375 << " tooltip=" << paletteToString(*m_palettes[ToolTipPalette]);
378 void QWindowsTheme::clearFonts()
380 qDeleteAll(m_fonts, m_fonts + NFonts);
381 qFill(m_fonts, m_fonts + NFonts, static_cast<QFont *>(0));
384 void QWindowsTheme::refreshFonts()
386 #ifndef Q_OS_WINCE // ALL THIS FUNCTIONALITY IS MISSING ON WINCE
388 if (!QGuiApplication::desktopSettingsAware())
390 NONCLIENTMETRICS ncm;
391 ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICS, lfMessageFont) + sizeof(LOGFONT);
392 SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize , &ncm, 0);
394 const QFont menuFont = QWindowsFontDatabase::LOGFONT_to_QFont(ncm.lfMenuFont);
395 const QFont messageBoxFont = QWindowsFontDatabase::LOGFONT_to_QFont(ncm.lfMessageFont);
396 const QFont statusFont = QWindowsFontDatabase::LOGFONT_to_QFont(ncm.lfStatusFont);
397 const QFont titleFont = QWindowsFontDatabase::LOGFONT_to_QFont(ncm.lfCaptionFont);
399 LOGFONT lfIconTitleFont;
400 SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0);
401 const QFont iconTitleFont = QWindowsFontDatabase::LOGFONT_to_QFont(lfIconTitleFont);
403 m_fonts[SystemFont] = new QFont(QWindowsFontDatabase::systemDefaultFont());
404 m_fonts[MenuFont] = new QFont(menuFont);
405 m_fonts[MenuBarFont] = new QFont(menuFont);
406 m_fonts[MessageBoxFont] = new QFont(messageBoxFont);
407 m_fonts[TipLabelFont] = new QFont(statusFont);
408 m_fonts[StatusBarFont] = new QFont(statusFont);
409 m_fonts[MdiSubWindowTitleFont] = new QFont(titleFont);
410 m_fonts[DockWidgetTitleFont] = new QFont(titleFont);
411 m_fonts[ItemViewFont] = new QFont(iconTitleFont);
413 if (QWindowsContext::verboseTheming)
414 qDebug() << __FUNCTION__ << '\n'
415 << " menuFont=" << menuFont
416 << " messageBox=" << MessageBoxFont;
417 #endif // !Q_OS_WINCE
420 bool QWindowsTheme::usePlatformNativeDialog(DialogType type) const
422 return QWindowsDialogs::useHelper(type);
425 QPlatformDialogHelper *QWindowsTheme::createPlatformDialogHelper(DialogType type) const
427 return QWindowsDialogs::createHelper(type);
430 void QWindowsTheme::windowsThemeChanged(QWindow * window)
433 QWindowSystemInterface::handleThemeChange(window);