Qt 6.x
The Qt SDK
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
qquickmacfocusframe.mm
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
5
6#include <AppKit/AppKit.h>
7
8#include <QtCore/qmetaobject.h>
9
10#include <QtGui/qguiapplication.h>
11#include <QtGui/private/qcoregraphics_p.h>
12
13#include <QtQml/qqmlengine.h>
14#include <QtQml/qqmlcontext.h>
15#include <QtQml/qqmlcomponent.h>
16
17#include <QtQuick/qquickitem.h>
18#include <QtQuick/private/qquicktextinput_p.h>
19#include <QtQuick/private/qquicktextedit_p.h>
20#include <QtQuick/private/qquickflickable_p.h>
21
22#include <QtQuickTemplates2/private/qquickframe_p.h>
23#include <QtQuickTemplates2/private/qquickbutton_p.h>
24#include <QtQuickTemplates2/private/qquickscrollview_p.h>
25#include <QtQuickTemplates2/private/qquickslider_p.h>
26#include <QtQuickTemplates2/private/qquickcombobox_p.h>
27#include <QtQuickTemplates2/private/qquickcheckbox_p.h>
28#include <QtQuickTemplates2/private/qquickradiobutton_p.h>
29#include <QtQuickTemplates2/private/qquickspinbox_p.h>
30#include <QtQuickTemplates2/private/qquicktextfield_p.h>
31#include <QtQuickTemplates2/private/qquicktextarea_p.h>
32
34#include "qquicknativestyle.h"
35
37
38Q_LOGGING_CATEGORY(lcFocusFrame, "qt.quick.controls.focusframe")
39
41QScopedPointer<QQuickItem> QQuickMacFocusFrame::m_focusFrame;
42
44{
46 if (auto item = qobject_cast<QQuickItem *>(qGuiApp->focusObject()))
47 moveToItem(item);
48 });
49}
50
51void QQuickMacFocusFrame::moveToItem(QQuickItem *item)
52{
53 if (!m_focusFrame) {
55 if (!context)
56 return;
57 createFocusFrame(context);
58 }
59
60 const QQuickFocusFrameDescription &config = getDescriptionForItem(item);
61 QMetaObject::invokeMethod(m_focusFrame.data(), "moveToItem",
65}
66
67void QQuickMacFocusFrame::createFocusFrame(QQmlContext *context)
68{
70 context->engine(),
72 "qrc:/qt-project.org/imports/QtQuick/NativeStyle/util/FocusFrame.qml")));
73 m_focusFrame.reset(qobject_cast<QQuickItem *>(component.create()));
74
75 auto indicatorColor = qt_mac_toQColor(NSColor.keyboardFocusIndicatorColor.CGColor);
76 indicatorColor.setAlpha(255);
77 m_focusFrame->setProperty("systemFrameColor", indicatorColor);
78}
79
80QQuickFocusFrameDescription QQuickMacFocusFrame::getDescriptionForItem(QQuickItem *focusItem) const
81{
82 qCDebug(lcFocusFrame) << "new focusobject:" << focusItem;
83 const auto parentItem = focusItem->parentItem();
84 if (!parentItem)
86
87 // The item that gets active focus can be a child of the control (e.g
88 // editable ComboBox). In that case, resolve the actual control first.
89 const auto proxy = focusItem->property("__focusFrameControl").value<QQuickItem *>();
90 const auto control = proxy ? proxy : focusItem;
91 auto target = control->property("__focusFrameTarget").value<QQuickItem *>();
92 qCDebug(lcFocusFrame) << "target:" << target;
93 qCDebug(lcFocusFrame) << "control:" << control;
94
95 if (!target) {
96 // __focusFrameTarget points to the item in the control that should
97 // get the focus frame. This is usually the control itself, but can
98 // sometimes be a child (CheckBox). We anyway require
99 // this property to be set if we are to show the focus frame around
100 // the control in the first place. So for controls that don't want
101 // a frame (ProgressBar), we simply skip setting it.
102 // Also, we should never show a focus frame around custom controls.
103 // None of the built-in styles do that, so to be consistent, we
104 // shouldn't either. Besides, drawing a focus frame around an unknown
105 // item without any way to turn it off can easily be unwanted. A better
106 // way for custom controls to get a native focus frame is for us to offer
107 // a FocusFrame control (QTBUG-86818).
109 }
110
111 // If the control gives us a QQuickStyleItem, we use that to configure the focus frame.
112 // By default we assume that the background delegate is a QQuickStyleItem, but the
113 // control can override this by setting __focusFrameStyleItem.
114 const auto styleItemProperty = control->property("__focusFrameStyleItem");
115 auto item = styleItemProperty.value<QQuickItem *>();
116 if (!item) {
117 const auto styleItemProperty = control->property("background");
118 item = styleItemProperty.value<QQuickItem *>();
119 }
120 qCDebug(lcFocusFrame) << "styleItem:" << item;
121 if (!item)
123 if (QQuickStyleItem *styleItem = qobject_cast<QQuickStyleItem *>(item))
124 return { target, QQuickStyleMargins(styleItem->layoutMargins()), styleItem->focusFrameRadius() };
125
126 // Some controls don't have a QQuickStyleItem. But if the __focusFrameStyleItem
127 // has a "__isDefaultDelegate" property set, we show a default focus frame instead.
128 if (item->property("__isDefaultDelegate").toBool() == true) {
129 qCDebug(lcFocusFrame) << "'__isDefaultDelegate' property found, showing a default focus frame";
130 const QStyleOption opt;
131 const qreal radius = QQuickNativeStyle::style()->pixelMetric(QStyle::PM_TextFieldFocusFrameRadius, &opt);
132 return { target, QQuickStyleMargins(), radius };
133 }
134
135 // The application has set a custom delegate on the control. In that
136 // case, it's the delegates responsibility to draw a focus frame.
137 qCDebug(lcFocusFrame) << "custom delegates in use, skip showing focus frame";
139}
140
void focusObjectChanged(QObject *focusObject)
This signal is emitted when final receiver of events tied to focus is changed.
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2823
QVariant property(const char *name) const
Returns the value of the object's name property.
Definition qobject.cpp:4187
bool setProperty(const char *name, const QVariant &value)
Sets the value of the object's name property to value.
virtual int pixelMetric(PixelMetric metric, const QStyleOption *option=nullptr) const =0
The QQmlComponent class encapsulates a QML component definition.
The QQmlContext class defines a context within a QML engine.
Definition qqmlcontext.h:25
static QQmlContext * contextForObject(const QObject *)
Returns the QQmlContext for the object, or nullptr if no context has been set.
The QQuickItem class provides the most basic of all visual items in \l {Qt Quick}.
Definition qquickitem.h:64
QQuickItem * parentItem() const
\inmodule QtCore
T * data() const noexcept
Returns the value of the pointer referenced by this object.
void reset(T *other=nullptr) noexcept(noexcept(Cleanup::cleanup(std::declval< T * >())))
Deletes the existing object it is pointing to (if any), and sets its pointer to other.
The QStyleOption class stores the parameters used by QStyle functions.
\inmodule QtCore
Definition qurl.h:94
\inmodule QtCore
Definition qvariant.h:64
T value() const &
Definition qvariant.h:511
static auto fromValue(T &&value) noexcept(std::is_nothrow_copy_constructible_v< T > &&Private::CanUseInternalSpace< T >) -> std::enable_if_t< std::conjunction_v< std::is_copy_constructible< T >, std::is_destructible< T > >, QVariant >
Definition qvariant.h:531
QStyleOptionButton opt
Combined button and popup list for selecting options.
static void * context
QColor qt_mac_toQColor(CGColorRef color)
EGLConfig config
#define qGuiApp
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
@ Invalid
#define Q_ARG(Type, data)
Definition qobjectdefs.h:62
GLenum target
static qreal component(const QPointF &point, unsigned int i)
QQuickItem * qobject_cast< QQuickItem * >(QObject *o)
Definition qquickitem.h:483
#define QStringLiteral(str)
double qreal
Definition qtypes.h:92
QGraphicsItem * item
QNetworkProxy proxy
[0]
static bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType, QGenericReturnArgument ret, QGenericArgument val0=QGenericArgument(nullptr), QGenericArgument val1=QGenericArgument(), QGenericArgument val2=QGenericArgument(), QGenericArgument val3=QGenericArgument(), QGenericArgument val4=QGenericArgument(), QGenericArgument val5=QGenericArgument(), QGenericArgument val6=QGenericArgument(), QGenericArgument val7=QGenericArgument(), QGenericArgument val8=QGenericArgument(), QGenericArgument val9=QGenericArgument())
\threadsafe This is an overloaded member function, provided for convenience. It differs from the abov...
static QQuickFocusFrameDescription Invalid