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
qquicknativestyle.cpp
Go to the documentation of this file.
1// Copyright (C) 2025 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
6
7#include <QtCore/qapplicationstatic.h>
8#include <QtCore/qloggingcategory.h>
9#include <QtCore/qthread.h>
10#include <QtGui/qguiapplication.h>
11#include <QtGui/qstylehints.h>
12
13#if defined(Q_OS_MACOS)
14# include "qquickmacstyle_mac_p.h"
15#elif defined(Q_OS_WINDOWS)
16# include "qquickwindowsxpstyle_p.h"
17#endif
18
19#include <memory>
20
22
23Q_STATIC_LOGGING_CATEGORY(lcNativeStylePlugin, "qt.quick.plugins.nativestyle");
24
25namespace QQC2 {
26
27namespace {
28
29// When we delete QStyle, it will free up its own internal resources. Especially
30// on macOS, this means releasing a lot of NSViews and NSCells from the QMacStyle
31// destructor. If we did this from ~QtQuickControls2NativeStylePlugin, it would
32// happen when the plugin was unloaded from a Q_DESTRUCTOR_FUNCTION in QLibrary,
33// which is very late in the tear-down process, and after qGuiApp has been set to
34// nullptr, NSApplication has stopped running, and perhaps also other static platform
35// variables (e.g in AppKit?) have been deleted. And to our best guess, this is also why
36// we see a crash in AppKit from the destructor in QMacStyle. So for this reason, we
37// delete QStyle from a post routine rather than from the destructor.
38//
39// Furthermore we need to ensure to recreate the QQuickFocusFrame when re-creating the qApplication
40
41struct StyleSingleton
42{
43 StyleSingleton();
44 ~StyleSingleton();
45 QStyle *style() { return m_style.get(); }
46
47private:
48 std::unique_ptr<QStyle> m_style;
49};
50
51Q_APPLICATION_STATIC(StyleSingleton, styleSingleton);
52
53StyleSingleton::StyleSingleton()
54{
55 qCDebug(lcNativeStylePlugin) << "Creating native style";
56
57 // Enable commonstyle as a reference style while
58 // the native styles are under development.
59 if (qEnvironmentVariable("QQC2_COMMONSTYLE") == u"true")
60 m_style = std::make_unique<QCommonStyle>();
61 else if (const QString envStyle = qEnvironmentVariable("QQC2_STYLE"); !envStyle.isNull()) {
62 if (envStyle == u"common")
63 m_style = std::make_unique<QCommonStyle>();
64#if defined(Q_OS_MACOS)
65 else if (envStyle == u"mac")
66 m_style.reset(QMacStyle::create());
67#endif
68#if defined(Q_OS_WINDOWS)
69 else if (envStyle == u"windows")
70 m_style = std::make_unique<QWindowsStyle>();
71 else if (envStyle == u"windowsxp")
72 m_style = std::make_unique<QWindowsXPStyle>();
73#endif
74 }
75
76 if (!m_style) {
77#if defined(Q_OS_MACOS)
78 m_style.reset(QMacStyle::create());
79#elif defined(Q_OS_WINDOWS)
80 m_style = std::make_unique<QWindowsXPStyle>();
81 if (QGuiApplication::styleHints()->colorScheme() == Qt::ColorScheme::Dark)
82 qobject_cast<QWindowsStyle *>(m_style.get())->refreshPalette();
83#endif
84 }
85
86 if (!m_style)
87 m_style = std::make_unique<QCommonStyle>();
88
89 // The native style plugin is neither the current style or fallback style
90 // during QQuickStylePlugin::registerTypes, so it's not given a chance to
91 // initialize or update the theme. But since it's used as an implementation
92 // detail of some of the other style plugins, it might need to know about
93 // theme changes.
94 Q_ASSERT(m_style->thread()->isMainThread());
95 QObject::connect(QGuiApplication::styleHints(), &QStyleHints::colorSchemeChanged, m_style.get(),
96 [this] {
97 m_style->handleThemeChange();
98 });
99}
100
101StyleSingleton::~StyleSingleton()
102{
103 qCDebug(lcNativeStylePlugin) << "Destroying native style";
104
105 m_style.reset();
106}
107
108}; // namespace
109
111{
112 return styleSingleton()->style();
113}
114
115} // namespace QQC2
116
117QT_END_NAMESPACE
QStyle * style()
Q_STATIC_LOGGING_CATEGORY(lcAccessibilityCore, "qt.accessibility.core")