/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtWidgets module 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 "qwindowsxpstyle_p.h"
#include "qwindowsxpstyle_p_p.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#if QT_CONFIG(toolbutton)
#include
#endif
#if QT_CONFIG(tabbar)
#include
#endif
#if QT_CONFIG(combobox)
#include
#endif
#if QT_CONFIG(scrollbar)
#include
#endif
#include
#if QT_CONFIG(spinbox)
#include
#endif
#if QT_CONFIG(listview)
#include
#endif
#if QT_CONFIG(stackedwidget)
#include
#endif
#if QT_CONFIG(pushbutton)
#include
#endif
#if QT_CONFIG(toolbar)
#include
#endif
#include
#include
#include
#include
QT_BEGIN_NAMESPACE
// General const values
static const int windowsItemFrame = 2; // menu item frame width
static const int windowsItemHMargin = 3; // menu item hor text margin
static const int windowsItemVMargin = 0; // menu item ver text margin
static const int windowsArrowHMargin = 6; // arrow horizontal margin
static const int windowsRightBorder = 12; // right border on windows
// External function calls
extern Q_WIDGETS_EXPORT HDC qt_win_display_dc();
extern QRegion qt_region_from_HRGN(HRGN rgn);
// Theme names matching the QWindowsXPStylePrivate::Theme enumeration.
static const wchar_t *themeNames[QWindowsXPStylePrivate::NThemes] =
{
L"BUTTON", L"COMBOBOX", L"EDIT", L"HEADER", L"LISTVIEW",
L"MENU", L"PROGRESS", L"REBAR", L"SCROLLBAR", L"SPIN",
L"TAB", L"TASKDIALOG", L"TOOLBAR", L"TOOLTIP", L"TRACKBAR",
L"TREEVIEW", L"WINDOW", L"STATUS", L"TREEVIEW"
};
static inline QBackingStore *backingStoreForWidget(const QWidget *widget)
{
if (QBackingStore *backingStore = widget->backingStore())
return backingStore;
if (const QWidget *topLevel = widget->nativeParentWidget())
if (QBackingStore *topLevelBackingStore = topLevel->backingStore())
return topLevelBackingStore;
return nullptr;
}
static inline HDC hdcForWidgetBackingStore(const QWidget *widget)
{
if (QBackingStore *backingStore = backingStoreForWidget(widget)) {
QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface();
if (nativeInterface)
return static_cast(nativeInterface->nativeResourceForBackingStore(QByteArrayLiteral("getDC"), backingStore));
}
return nullptr;
}
// Theme data helper ------------------------------------------------------------------------------
/* \internal
Returns \c true if the themedata is valid for use.
*/
bool XPThemeData::isValid()
{
return QWindowsXPStylePrivate::useXP() && theme >= 0 && handle();
}
/* \internal
Returns the theme engine handle to the specific class.
If the handle hasn't been opened before, it opens the data, and
adds it to a static map, for caching.
*/
HTHEME XPThemeData::handle()
{
if (!QWindowsXPStylePrivate::useXP())
return nullptr;
if (!htheme)
htheme = QWindowsXPStylePrivate::createTheme(theme, QWindowsXPStylePrivate::winId(widget));
return htheme;
}
/* \internal
Converts a QRect to the native RECT structure.
*/
RECT XPThemeData::toRECT(const QRect &qr)
{
RECT r;
r.left = qr.x();
r.right = qr.x() + qr.width();
r.top = qr.y();
r.bottom = qr.y() + qr.height();
return r;
}
/* \internal
Returns the native region of a part, if the part is considered
transparent. The region is scaled to the parts size (rect).
*/
HRGN XPThemeData::mask(QWidget *widget)
{
if (!IsThemeBackgroundPartiallyTransparent(handle(), partId, stateId))
return nullptr;
HRGN hrgn;
HDC dc = nullptr;
if (widget)
dc = hdcForWidgetBackingStore(widget);
RECT nativeRect = toRECT(rect);
GetThemeBackgroundRegion(handle(), dc, partId, stateId, &nativeRect, &hrgn);
return hrgn;
}
// QWindowsXPStylePrivate -------------------------------------------------------------------------
// Static initializations
HWND QWindowsXPStylePrivate::m_vistaTreeViewHelper = nullptr;
HTHEME QWindowsXPStylePrivate::m_themes[NThemes];
bool QWindowsXPStylePrivate::use_xp = false;
QBasicAtomicInt QWindowsXPStylePrivate::ref = Q_BASIC_ATOMIC_INITIALIZER(-1); // -1 based refcounting
static void qt_add_rect(HRGN &winRegion, QRect r)
{
HRGN rgn = CreateRectRgn(r.left(), r.top(), r.x() + r.width(), r.y() + r.height());
if (rgn) {
HRGN dest = CreateRectRgn(0,0,0,0);
int result = CombineRgn(dest, winRegion, rgn, RGN_OR);
if (result) {
DeleteObject(winRegion);
winRegion = dest;
}
DeleteObject(rgn);
}
}
static HRGN qt_hrgn_from_qregion(const QRegion ®ion)
{
HRGN hRegion = CreateRectRgn(0,0,0,0);
if (region.rectCount() == 1) {
qt_add_rect(hRegion, region.boundingRect());
return hRegion;
}
for (const QRect &rect : region)
qt_add_rect(hRegion, rect);
return hRegion;
}
/* \internal
Checks if the theme engine can/should be used, or if we should
fall back to Windows style.
*/
bool QWindowsXPStylePrivate::useXP(bool update)
{
if (!update)
return use_xp;
return use_xp = IsThemeActive() && (IsAppThemed() || !QCoreApplication::instance());
}
/* \internal
Handles refcounting, and queries the theme engine for usage.
*/
void QWindowsXPStylePriv