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
4#include <QtQml/qqml.h>
5#include <QtQuickControls2/private/qquickstyleplugin_p.h>
6#include <QtGui/qguiapplication.h>
7#include <QtGui/qpa/qplatformintegration.h>
8#include <QtGui/private/qguiapplication_p.h>
9#include <QtGui/qstylehints.h>
10#include <QtQuickTemplates2/private/qquicktheme_p.h>
11
12#include "qquicknativestyle.h"
13#include "qquickcommonstyle.h"
14
15#if defined(Q_OS_MACOS)
16#include "qquickmacfocusframe.h"
17#include "qquickmacstyle_mac_p.h"
18#elif defined(Q_OS_WINDOWS)
19#include "qquickwindowsfocusframe.h"
20#include "qquickwindowsxpstyle_p.h"
21#endif
22
23QT_BEGIN_NAMESPACE
24
25extern void qml_register_types_QtQuick_NativeStyle();
26Q_GHS_KEEP_REFERENCE(qml_register_types_QtQuick_NativeStyle);
27
28using namespace QQC2;
29
30class QtQuickControls2NativeStylePlugin : public QQuickStylePlugin
31{
32 Q_OBJECT
33 Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
34
35public:
36 QtQuickControls2NativeStylePlugin(QObject *parent = nullptr);
37 ~QtQuickControls2NativeStylePlugin() override;
38
39 void initializeEngine(QQmlEngine *engine, const char *uri) override;
40 void initializeTheme(QQuickTheme *theme) override;
41 QString name() const override;
42
43#if defined(Q_OS_MACOS) || defined (Q_OS_WIN)
44 QScopedPointer<QQuickFocusFrame> m_focusFrame;
45#endif
46};
47
48static void deleteQStyle()
49{
50 // When we delete QStyle, it will free up it's own internal resources. Especially
51 // on macOS, this means releasing a lot of NSViews and NSCells from the QMacStyle
52 // destructor. If we did this from ~QtQuickControls2NativeStylePlugin, it would
53 // happen when the plugin was unloaded from a Q_DESTRUCTOR_FUNCTION in QLibrary,
54 // which is very late in the tear-down process, and after qGuiApp has been set to
55 // nullptr, NSApplication has stopped running, and perhaps also other static platform
56 // variables (e.g in AppKit?) has been deleted. And to our best guess, this is also why
57 // we see a crash in AppKit from the destructor in QMacStyle. So for this reason, we
58 // delete QStyle from a post routine rather than from the destructor.
59 QQuickNativeStyle::setStyle(nullptr);
60}
61
62QtQuickControls2NativeStylePlugin::QtQuickControls2NativeStylePlugin(QObject *parent):
63 QQuickStylePlugin(parent)
64{
65 volatile auto registration = &qml_register_types_QtQuick_NativeStyle;
66 Q_UNUSED(registration);
67}
68
69QtQuickControls2NativeStylePlugin::~QtQuickControls2NativeStylePlugin()
70{
71 if (!qGuiApp)
72 return;
73
74 // QGuiApplication is still running, so we need to remove the post
75 // routine to not be called after we have been unloaded.
76 qRemovePostRoutine(deleteQStyle);
77 QQuickNativeStyle::setStyle(nullptr);
78}
79
80QString QtQuickControls2NativeStylePlugin::name() const
81{
82 return QStringLiteral("NativeStyle");
83}
84
85void QtQuickControls2NativeStylePlugin::initializeEngine(QQmlEngine *engine, const char *uri)
86{
87 Q_UNUSED(engine);
88 Q_UNUSED(uri);
89 // Enable commonstyle as a reference style while
90 // the native styles are under development.
91 QStyle *style = nullptr;
92 if (qEnvironmentVariable(varName: "QQC2_COMMONSTYLE") == QStringLiteral("true")) {
93 style = new QCommonStyle;
94 } else {
95 const QString envStyle = qEnvironmentVariable(varName: "QQC2_STYLE");
96 if (!envStyle.isNull()) {
97 if (envStyle == QLatin1String("common"))
98 style = new QCommonStyle;
99#if defined(Q_OS_MACOS)
100 else if (envStyle == QLatin1String("mac"))
101 style = new QMacStyle;
102#endif
103#if defined(Q_OS_WINDOWS)
104 else if (envStyle == QLatin1String("windows"))
105 style = new QWindowsStyle;
106 else if (envStyle == QLatin1String("windowsxp"))
107 style = new QWindowsXPStyle;
108#endif
109 }
110 if (!style) {
111#if defined(Q_OS_MACOS)
112 style = new QMacStyle;
113#elif defined(Q_OS_WINDOWS)
114 style = new QWindowsXPStyle;
115 if (QGuiApplication::styleHints()->colorScheme() == Qt::ColorScheme::Dark)
116 qobject_cast<QWindowsStyle *>(style)->refreshPalette();
117#else
118 style = new QCommonStyle;
119#endif
120 }
121 }
122
123#if defined(Q_OS_MACOS)
124 m_focusFrame.reset(new QQuickMacFocusFrame());
125#elif defined(Q_OS_WIN)
126 m_focusFrame.reset(new QQuickWindowsFocusFrame());
127#endif
128
129 qAddPostRoutine(deleteQStyle);
130 QQuickNativeStyle::setStyle(style);
131}
132
133void QtQuickControls2NativeStylePlugin::initializeTheme(QQuickTheme * /*theme*/)
134{
135}
136
137QT_END_NAMESPACE
138
139#include "qtquickcontrols2nativestyleplugin.moc"
140

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

source code of qtdeclarative/src/quicknativestyle/qtquickcontrols2nativestyleplugin.cpp