Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qtquickcontrols2nativestyleplugin.cpp
Go to the documentation of this file.
1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#include <QtQml/qqml.h>
6#include <QtQuickControls2/private/qquickstyleplugin_p.h>
7#include <QtGui/qguiapplication.h>
8#include <QtGui/qpa/qplatformintegration.h>
9#include <QtGui/private/qguiapplication_p.h>
10#include <QtGui/qstylehints.h>
11#include <QtQuickTemplates2/private/qquicktheme_p.h>
12
15
16#if defined(Q_OS_MACOS)
17#include "qquickmacfocusframe.h"
18#include "qquickmacstyle_mac_p.h"
19#elif defined(Q_OS_WINDOWS)
20#include "qquickwindowsfocusframe.h"
21#include "qquickwindowsxpstyle_p.h"
22#endif
23
25
28
29using namespace QQC2;
30
32{
33 Q_OBJECT
34 Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
35
36public:
39
40 void initializeEngine(QQmlEngine *engine, const char *uri) override;
41 void initializeTheme(QQuickTheme *theme) override;
42 QString name() const override;
43
44#if defined(Q_OS_MACOS) || defined (Q_OS_WIN)
46#endif
47};
48
49static void deleteQStyle()
50{
51 // When we delete QStyle, it will free up it's own internal resources. Especially
52 // on macOS, this means releasing a lot of NSViews and NSCells from the QMacStyle
53 // destructor. If we did this from ~QtQuickControls2NativeStylePlugin, it would
54 // happen when the plugin was unloaded from a Q_DESTRUCTOR_FUNCTION in QLibrary,
55 // which is very late in the tear-down process, and after qGuiApp has been set to
56 // nullptr, NSApplication has stopped running, and perhaps also other static platform
57 // variables (e.g in AppKit?) has been deleted. And to our best guess, this is also why
58 // we see a crash in AppKit from the destructor in QMacStyle. So for this reason, we
59 // delete QStyle from a post routine rather than from the destructor.
61}
62
63QtQuickControls2NativeStylePlugin::QtQuickControls2NativeStylePlugin(QObject *parent):
64 QQuickStylePlugin(parent)
65{
66 volatile auto registration = &qml_register_types_QtQuick_NativeStyle;
67 Q_UNUSED(registration);
68}
69
71{
72 if (!qGuiApp)
73 return;
74
75 // QGuiApplication is still running, so we need to remove the post
76 // routine to not be called after we have been unloaded.
77 qRemovePostRoutine(deleteQStyle);
79}
80
82{
83 return QStringLiteral("NativeStyle");
84}
85
86void QtQuickControls2NativeStylePlugin::initializeEngine(QQmlEngine *engine, const char *uri)
87{
88 Q_UNUSED(engine);
89 Q_UNUSED(uri);
90 // Enable commonstyle as a reference style while
91 // the native styles are under development.
92 QStyle *style = nullptr;
93 if (qEnvironmentVariable("QQC2_COMMONSTYLE") == QStringLiteral("true")) {
94 style = new QCommonStyle;
95 } else {
96 const QString envStyle = qEnvironmentVariable("QQC2_STYLE");
97 if (!envStyle.isNull()) {
98 if (envStyle == QLatin1String("common"))
99 style = new QCommonStyle;
100#if defined(Q_OS_MACOS)
101 else if (envStyle == QLatin1String("mac"))
102 style = QMacStyle::create();
103#endif
104#if defined(Q_OS_WINDOWS)
105 else if (envStyle == QLatin1String("windows"))
106 style = new QWindowsStyle;
107 else if (envStyle == QLatin1String("windowsxp"))
108 style = new QWindowsXPStyle;
109#endif
110 }
111 if (!style) {
112#if defined(Q_OS_MACOS)
113 style = QMacStyle::create();
114#elif defined(Q_OS_WINDOWS)
115 style = new QWindowsXPStyle;
116 if (QGuiApplication::styleHints()->colorScheme() == Qt::ColorScheme::Dark)
117 qobject_cast<QWindowsStyle *>(style)->refreshPalette();
118#else
119 style = new QCommonStyle;
120#endif
121 }
122 }
123
124#if defined(Q_OS_MACOS)
125 m_focusFrame.reset(new QQuickMacFocusFrame());
126#elif defined(Q_OS_WIN)
127 m_focusFrame.reset(new QQuickWindowsFocusFrame());
128#endif
129
130 // The native style plugin is neither the current style or fallback style
131 // during QQuickStylePlugin::registerTypes, so it's not given a chance to
132 // initialize or update the theme. But since it's used as an implementation
133 // detail of some of the other style plugins, it might need to know about
134 // theme changes.
135 Q_ASSERT(style->thread()->isMainThread());
136 connect(QGuiApplication::styleHints(), &QStyleHints::colorSchemeChanged,
137 style, [=]{ style->handleThemeChange(); });
138
139 qAddPostRoutine(deleteQStyle);
141}
142
144{
145}
146
147QT_END_NAMESPACE
148
149#include "qtquickcontrols2nativestyleplugin.moc"
static void setStyle(QStyle *style)
void initializeEngine(QQmlEngine *engine, const char *uri) override
Initializes the extension from the uri using the engine.
QT_BEGIN_NAMESPACE void qml_register_types_QtQuick_NativeStyle()
Q_GHS_KEEP_REFERENCE(qml_register_types_QtQuick_NativeStyle)
static void deleteQStyle()