QWindowsXP/VistaStyle: Move the Vista treeview handling to QWindowsXPStylePrivate.
QWindowsXPStylePrivate maintains a list of theme handles for various style items. The derived class QWindowsVistaStylePrivate had logic to use a special helper window with the "explorer" window theme set to obtain the correct treeview arrow branch indicator (arrow shape for Vista as opposed to '+'/'-' on Windows XP) when creating the "TREEVIEW" theme. This required calling the helper function QWindowsVistaStylePrivate::initTreeViewTheming() before QWindowsXPStylePrivate::createTheme(), which is prone to errors and initialization order issues. This could be solved by making QWindowsXPStylePrivate::createTheme() virtual or similar, but since it the fate of QWindowsXPStylePrivate is most likely to be merged into QWindowsVistaStylePrivate; it was decided to move the entire special handling of the Vista treeviews into QWindowsXPStylePrivate. The existing enumeration value QWindowsXPStylePrivate::TreeViewTheme is renamed to QWindowsXPStylePrivate::XpTreeViewTheme and a new value QWindowsXPStylePrivate::VistaTreeViewTheme is added for which QWindowsXPStylePrivate::createTheme() invokes the special handling. This also removes the need to destroy the helper window in unpolish(), which should save some initializations. Task-number: QTBUG-52230 Change-Id: I0492ecf38fb3e5eabc4ecbdef70f0bf05e82e104 Reviewed-by: Adam Light <aclight@gmail.com> Reviewed-by: Joerg Bornemann <joerg.bornemann@theqtcompany.com>
This commit is contained in:
parent
4d10e55d4d
commit
f1e0eedcf5
@ -420,9 +420,9 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt
|
|||||||
|
|
||||||
case PE_IndicatorBranch:
|
case PE_IndicatorBranch:
|
||||||
{
|
{
|
||||||
XPThemeData theme(widget, painter, QWindowsXPStylePrivate::TreeViewTheme);
|
XPThemeData theme(widget, painter, QWindowsXPStylePrivate::VistaTreeViewTheme);
|
||||||
static int decoration_size = 0;
|
static int decoration_size = 0;
|
||||||
if (!decoration_size && d->initTreeViewTheming() && theme.isValid()) {
|
if (!decoration_size && theme.isValid()) {
|
||||||
XPThemeData themeSize = theme;
|
XPThemeData themeSize = theme;
|
||||||
themeSize.partId = TVP_HOTGLYPH;
|
themeSize.partId = TVP_HOTGLYPH;
|
||||||
themeSize.stateId = GLPS_OPENED;
|
themeSize.stateId = GLPS_OPENED;
|
||||||
@ -722,9 +722,9 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt
|
|||||||
|
|
||||||
QPainter pixmapPainter(&pixmap);
|
QPainter pixmapPainter(&pixmap);
|
||||||
XPThemeData theme(widget, &pixmapPainter,
|
XPThemeData theme(widget, &pixmapPainter,
|
||||||
QWindowsXPStylePrivate::TreeViewTheme,
|
QWindowsXPStylePrivate::VistaTreeViewTheme,
|
||||||
LVP_LISTITEM, state, QRect(0, 0, sectionSize.width(), sectionSize.height()));
|
LVP_LISTITEM, state, QRect(0, 0, sectionSize.width(), sectionSize.height()));
|
||||||
if (d->initTreeViewTheming() && theme.isValid()) {
|
if (theme.isValid()) {
|
||||||
d->drawBackground(theme);
|
d->drawBackground(theme);
|
||||||
} else {
|
} else {
|
||||||
QWindowsXPStyle::drawPrimitive(PE_PanelItemViewItem, option, painter, widget);
|
QWindowsXPStyle::drawPrimitive(PE_PanelItemViewItem, option, painter, widget);
|
||||||
@ -2351,10 +2351,6 @@ void QWindowsVistaStyle::unpolish(QWidget *widget)
|
|||||||
QWindowsXPStyle::unpolish(widget);
|
QWindowsXPStyle::unpolish(widget);
|
||||||
|
|
||||||
QWindowsVistaStylePrivate *d = d_func();
|
QWindowsVistaStylePrivate *d = d_func();
|
||||||
// Delete the tree view helper in case the XP style cleaned the
|
|
||||||
// theme handle map due to a theme or QStyle change (QProxyStyle).
|
|
||||||
if (!QWindowsXPStylePrivate::hasTheme(QWindowsXPStylePrivate::TreeViewTheme))
|
|
||||||
d->cleanupTreeViewTheming();
|
|
||||||
|
|
||||||
d->stopAnimation(widget);
|
d->stopAnimation(widget);
|
||||||
|
|
||||||
@ -2420,15 +2416,10 @@ QPixmap QWindowsVistaStyle::standardPixmap(StandardPixmap standardPixmap, const
|
|||||||
}
|
}
|
||||||
|
|
||||||
QWindowsVistaStylePrivate::QWindowsVistaStylePrivate() :
|
QWindowsVistaStylePrivate::QWindowsVistaStylePrivate() :
|
||||||
QWindowsXPStylePrivate(), m_treeViewHelper(0)
|
QWindowsXPStylePrivate()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
QWindowsVistaStylePrivate::~QWindowsVistaStylePrivate()
|
|
||||||
{
|
|
||||||
cleanupTreeViewTheming();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QWindowsVistaStylePrivate::transitionsEnabled() const
|
bool QWindowsVistaStylePrivate::transitionsEnabled() const
|
||||||
{
|
{
|
||||||
BOOL animEnabled = false;
|
BOOL animEnabled = false;
|
||||||
@ -2440,58 +2431,6 @@ bool QWindowsVistaStylePrivate::transitionsEnabled() const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* We need to set the windows "explorer" theme explicitly on a native
|
|
||||||
* window and open the "TREEVIEW" theme handle passing its window handle
|
|
||||||
* in order to get Vista-style item view themes (particulary drawBackground()
|
|
||||||
* for selected items needs this).
|
|
||||||
* We invoke a service of the native Windows interface to create
|
|
||||||
* a non-visible window handle, open the theme on it and insert it into
|
|
||||||
* the cache so that it is found by XPThemeData::handle() first.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static inline HWND createTreeViewHelperWindow()
|
|
||||||
{
|
|
||||||
if (QPlatformNativeInterface *ni = QGuiApplication::platformNativeInterface()) {
|
|
||||||
void *hwnd = 0;
|
|
||||||
void *wndProc = reinterpret_cast<void *>(DefWindowProc);
|
|
||||||
if (QMetaObject::invokeMethod(ni, "createMessageWindow", Qt::DirectConnection,
|
|
||||||
Q_RETURN_ARG(void *, hwnd),
|
|
||||||
Q_ARG(QString, QStringLiteral("QTreeViewThemeHelperWindowClass")),
|
|
||||||
Q_ARG(QString, QStringLiteral("QTreeViewThemeHelperWindow")),
|
|
||||||
Q_ARG(void *, wndProc)) && hwnd) {
|
|
||||||
return reinterpret_cast<HWND>(hwnd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QWindowsVistaStylePrivate::initTreeViewTheming()
|
|
||||||
{
|
|
||||||
if (m_treeViewHelper)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
m_treeViewHelper = createTreeViewHelperWindow();
|
|
||||||
if (!m_treeViewHelper) {
|
|
||||||
qWarning("Unable to create the treeview helper window.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const HRESULT hr = QWindowsXPStylePrivate::pSetWindowTheme(m_treeViewHelper, L"explorer", NULL);
|
|
||||||
if (hr != S_OK) {
|
|
||||||
qErrnoWarning("SetWindowTheme() failed.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return QWindowsXPStylePrivate::createTheme(QWindowsXPStylePrivate::TreeViewTheme, m_treeViewHelper);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QWindowsVistaStylePrivate::cleanupTreeViewTheming()
|
|
||||||
{
|
|
||||||
if (m_treeViewHelper) {
|
|
||||||
DestroyWindow(m_treeViewHelper);
|
|
||||||
m_treeViewHelper = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\reimp
|
\reimp
|
||||||
*/
|
*/
|
||||||
|
@ -162,16 +162,10 @@ class QWindowsVistaStylePrivate : public QWindowsXPStylePrivate
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
QWindowsVistaStylePrivate();
|
QWindowsVistaStylePrivate();
|
||||||
~QWindowsVistaStylePrivate();
|
|
||||||
static int fixedPixelMetric(QStyle::PixelMetric pm);
|
static int fixedPixelMetric(QStyle::PixelMetric pm);
|
||||||
static inline bool useVista();
|
static inline bool useVista();
|
||||||
bool transitionsEnabled() const;
|
bool transitionsEnabled() const;
|
||||||
|
|
||||||
private:
|
|
||||||
bool initTreeViewTheming();
|
|
||||||
void cleanupTreeViewTheming();
|
|
||||||
|
|
||||||
HWND m_treeViewHelper;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -48,6 +48,8 @@
|
|||||||
#include <qbackingstore.h>
|
#include <qbackingstore.h>
|
||||||
#include <qapplication.h>
|
#include <qapplication.h>
|
||||||
#include <qpixmapcache.h>
|
#include <qpixmapcache.h>
|
||||||
|
#include <private/qapplication_p.h>
|
||||||
|
#include <qpa/qplatformnativeinterface.h>
|
||||||
|
|
||||||
#include <qdesktopwidget.h>
|
#include <qdesktopwidget.h>
|
||||||
#include <qtoolbutton.h>
|
#include <qtoolbutton.h>
|
||||||
@ -157,7 +159,7 @@ static const wchar_t *themeNames[QWindowsXPStylePrivate::NThemes] =
|
|||||||
L"BUTTON", L"COMBOBOX", L"EDIT", L"HEADER", L"LISTVIEW",
|
L"BUTTON", L"COMBOBOX", L"EDIT", L"HEADER", L"LISTVIEW",
|
||||||
L"MENU", L"PROGRESS", L"REBAR", L"SCROLLBAR", L"SPIN",
|
L"MENU", L"PROGRESS", L"REBAR", L"SCROLLBAR", L"SPIN",
|
||||||
L"TAB", L"TASKDIALOG", L"TOOLBAR", L"TOOLTIP", L"TRACKBAR",
|
L"TAB", L"TASKDIALOG", L"TOOLBAR", L"TOOLTIP", L"TRACKBAR",
|
||||||
L"TREEVIEW", L"WINDOW", L"STATUS"
|
L"TREEVIEW", L"WINDOW", L"STATUS", L"TREEVIEW"
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline QBackingStore *backingStoreForWidget(const QWidget *widget)
|
static inline QBackingStore *backingStoreForWidget(const QWidget *widget)
|
||||||
@ -238,6 +240,7 @@ HRGN XPThemeData::mask(QWidget *widget)
|
|||||||
// QWindowsXPStylePrivate -------------------------------------------------------------------------
|
// QWindowsXPStylePrivate -------------------------------------------------------------------------
|
||||||
// Static initializations
|
// Static initializations
|
||||||
QPixmap *QWindowsXPStylePrivate::tabbody = 0;
|
QPixmap *QWindowsXPStylePrivate::tabbody = 0;
|
||||||
|
HWND QWindowsXPStylePrivate::m_vistaTreeViewHelper = 0;
|
||||||
HTHEME QWindowsXPStylePrivate::m_themes[NThemes];
|
HTHEME QWindowsXPStylePrivate::m_themes[NThemes];
|
||||||
bool QWindowsXPStylePrivate::use_xp = false;
|
bool QWindowsXPStylePrivate::use_xp = false;
|
||||||
QBasicAtomicInt QWindowsXPStylePrivate::ref = Q_BASIC_ATOMIC_INITIALIZER(-1); // -1 based refcounting
|
QBasicAtomicInt QWindowsXPStylePrivate::ref = Q_BASIC_ATOMIC_INITIALIZER(-1); // -1 based refcounting
|
||||||
@ -321,6 +324,58 @@ void QWindowsXPStylePrivate::cleanup(bool force)
|
|||||||
tabbody = 0;
|
tabbody = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* In order to obtain the correct VistaTreeViewTheme (arrows for PE_IndicatorBranch),
|
||||||
|
* we need to set the windows "explorer" theme explicitly on a native
|
||||||
|
* window and open the "TREEVIEW" theme handle passing its window handle
|
||||||
|
* in order to get Vista-style item view themes (particulary drawBackground()
|
||||||
|
* for selected items needs this).
|
||||||
|
* We invoke a service of the native Windows interface to create
|
||||||
|
* a non-visible window handle, open the theme on it and insert it into
|
||||||
|
* the cache so that it is found by XPThemeData::handle() first.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static inline HWND createTreeViewHelperWindow()
|
||||||
|
{
|
||||||
|
if (QPlatformNativeInterface *ni = QGuiApplication::platformNativeInterface()) {
|
||||||
|
void *hwnd = 0;
|
||||||
|
void *wndProc = reinterpret_cast<void *>(DefWindowProc);
|
||||||
|
if (QMetaObject::invokeMethod(ni, "createMessageWindow", Qt::DirectConnection,
|
||||||
|
Q_RETURN_ARG(void *, hwnd),
|
||||||
|
Q_ARG(QString, QStringLiteral("QTreeViewThemeHelperWindowClass")),
|
||||||
|
Q_ARG(QString, QStringLiteral("QTreeViewThemeHelperWindow")),
|
||||||
|
Q_ARG(void *, wndProc)) && hwnd) {
|
||||||
|
return reinterpret_cast<HWND>(hwnd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QWindowsXPStylePrivate::initVistaTreeViewTheming()
|
||||||
|
{
|
||||||
|
if (m_vistaTreeViewHelper)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
m_vistaTreeViewHelper = createTreeViewHelperWindow();
|
||||||
|
if (!m_vistaTreeViewHelper) {
|
||||||
|
qWarning("Unable to create the treeview helper window.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (FAILED(QWindowsXPStylePrivate::pSetWindowTheme(m_vistaTreeViewHelper, L"explorer", NULL))) {
|
||||||
|
qErrnoWarning("SetWindowTheme() failed.");
|
||||||
|
cleanupVistaTreeViewTheming();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QWindowsXPStylePrivate::cleanupVistaTreeViewTheming()
|
||||||
|
{
|
||||||
|
if (m_vistaTreeViewHelper) {
|
||||||
|
DestroyWindow(m_vistaTreeViewHelper);
|
||||||
|
m_vistaTreeViewHelper = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* \internal
|
/* \internal
|
||||||
Closes all open theme data handles to ensure that we don't leak
|
Closes all open theme data handles to ensure that we don't leak
|
||||||
resources, and that we don't refere to old handles when for
|
resources, and that we don't refere to old handles when for
|
||||||
@ -333,6 +388,7 @@ void QWindowsXPStylePrivate::cleanupHandleMap()
|
|||||||
pCloseThemeData(m_themes[i]);
|
pCloseThemeData(m_themes[i]);
|
||||||
m_themes[i] = 0;
|
m_themes[i] = 0;
|
||||||
}
|
}
|
||||||
|
QWindowsXPStylePrivate::cleanupVistaTreeViewTheming();
|
||||||
}
|
}
|
||||||
|
|
||||||
HTHEME QWindowsXPStylePrivate::createTheme(int theme, HWND hwnd)
|
HTHEME QWindowsXPStylePrivate::createTheme(int theme, HWND hwnd)
|
||||||
@ -343,6 +399,8 @@ HTHEME QWindowsXPStylePrivate::createTheme(int theme, HWND hwnd)
|
|||||||
}
|
}
|
||||||
if (!m_themes[theme]) {
|
if (!m_themes[theme]) {
|
||||||
const wchar_t *name = themeNames[theme];
|
const wchar_t *name = themeNames[theme];
|
||||||
|
if (theme == VistaTreeViewTheme && QWindowsXPStylePrivate::initVistaTreeViewTheming())
|
||||||
|
hwnd = QWindowsXPStylePrivate::m_vistaTreeViewHelper;
|
||||||
m_themes[theme] = pOpenThemeData(hwnd, name);
|
m_themes[theme] = pOpenThemeData(hwnd, name);
|
||||||
if (!m_themes[theme])
|
if (!m_themes[theme])
|
||||||
qErrnoWarning("OpenThemeData() failed for theme %d (%s).",
|
qErrnoWarning("OpenThemeData() failed for theme %d (%s).",
|
||||||
@ -1947,7 +2005,7 @@ case PE_Frame:
|
|||||||
bef_v -= delta;
|
bef_v -= delta;
|
||||||
aft_h += delta;
|
aft_h += delta;
|
||||||
aft_v += delta;
|
aft_v += delta;
|
||||||
XPThemeData theme(0, p, QWindowsXPStylePrivate::TreeViewTheme);
|
XPThemeData theme(0, p, QWindowsXPStylePrivate::XpTreeViewTheme);
|
||||||
theme.rect = QRect(bef_h, bef_v, decoration_size, decoration_size);
|
theme.rect = QRect(bef_h, bef_v, decoration_size, decoration_size);
|
||||||
theme.partId = TVP_GLYPH;
|
theme.partId = TVP_GLYPH;
|
||||||
theme.stateId = flags & QStyle::State_Open ? GLPS_OPENED : GLPS_CLOSED;
|
theme.stateId = flags & QStyle::State_Open ? GLPS_OPENED : GLPS_CLOSED;
|
||||||
|
@ -350,9 +350,10 @@ public:
|
|||||||
ToolBarTheme,
|
ToolBarTheme,
|
||||||
ToolTipTheme,
|
ToolTipTheme,
|
||||||
TrackBarTheme,
|
TrackBarTheme,
|
||||||
TreeViewTheme,
|
XpTreeViewTheme, // '+'/'-' shape treeview indicators (XP)
|
||||||
WindowTheme,
|
WindowTheme,
|
||||||
StatusTheme,
|
StatusTheme,
|
||||||
|
VistaTreeViewTheme, // arrow shape treeview indicators (Vista) obtained from "explorer" theme.
|
||||||
NThemes
|
NThemes
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -413,6 +414,9 @@ private:
|
|||||||
void showProperties(XPThemeData &themeData);
|
void showProperties(XPThemeData &themeData);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static bool initVistaTreeViewTheming();
|
||||||
|
static void cleanupVistaTreeViewTheming();
|
||||||
|
|
||||||
static QBasicAtomicInt ref;
|
static QBasicAtomicInt ref;
|
||||||
static bool use_xp;
|
static bool use_xp;
|
||||||
static QPixmap *tabbody;
|
static QPixmap *tabbody;
|
||||||
@ -424,6 +428,7 @@ private:
|
|||||||
uchar *bufferPixels;
|
uchar *bufferPixels;
|
||||||
int bufferW, bufferH;
|
int bufferW, bufferH;
|
||||||
|
|
||||||
|
static HWND m_vistaTreeViewHelper;
|
||||||
static HTHEME m_themes[NThemes];
|
static HTHEME m_themes[NThemes];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user