Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qquickfocusframe.cpp
Go to the documentation of this file.
1// Copyright (C) 2023 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 "qquickfocusframe.h"
5
6#include <QtCore/qmetaobject.h>
7
8#include <QtGui/qguiapplication.h>
9
10#include <QtQml/qqmlengine.h>
11#include <QtQml/qqmlcontext.h>
12#include <QtQml/qqmlcomponent.h>
13
14#include <QtQuick/qquickitem.h>
15
17
19
20Q_LOGGING_CATEGORY(lcFocusFrame, "qt.quick.controls.focusframe")
21
23QScopedPointer<QQuickItem> QQuickFocusFrame::m_focusFrame;
24
26{
28 if (auto item = qobject_cast<QQuickItem *>(qGuiApp->focusObject()))
29 moveToItem(item);
30 });
31}
32
33void QQuickFocusFrame::moveToItem(QQuickItem *item)
34{
35 if (!m_focusFrame) {
37 // In certain cases like QQuickWebEngineView, the item
38 // gets focus even though it has no QQmlEngine associated with its context.
39 // We need the engine for creating the focus frame component.
40 if (!context || !context->engine())
41 return;
42 m_focusFrame.reset(createFocusFrame(context));
43 if (!m_focusFrame) {
44 qWarning() << "Failed to create FocusFrame";
45 return;
46 }
47 }
48
49 const QQuickFocusFrameDescription &config = getDescriptionForItem(item);
50 QMetaObject::invokeMethod(m_focusFrame.data(), "moveToItem",
54}
55
56QQuickFocusFrameDescription QQuickFocusFrame::getDescriptionForItem(QQuickItem *focusItem) const
57{
58 qCDebug(lcFocusFrame) << "new focusobject:" << focusItem;
59 const auto parentItem = focusItem->parentItem();
60 if (!parentItem)
62
63 // The item that gets active focus can be a child of the control (e.g
64 // editable ComboBox). In that case, resolve the actual control first.
65 const auto proxy = focusItem->property("__focusFrameControl").value<QQuickItem *>();
66 const auto control = proxy ? proxy : focusItem;
67 auto target = control->property("__focusFrameTarget").value<QQuickItem *>();
68 qCDebug(lcFocusFrame) << "target:" << target;
69 qCDebug(lcFocusFrame) << "control:" << control;
70
71 if (!target) {
72 // __focusFrameTarget points to the item in the control that should
73 // get the focus frame. This is usually the control itself, but can
74 // sometimes be a child (CheckBox). We anyway require
75 // this property to be set if we are to show the focus frame around
76 // the control in the first place. So for controls that don't want
77 // a frame (ProgressBar), we simply skip setting it.
78 // Also, we should never show a focus frame around custom controls.
79 // None of the built-in styles do that, so to be consistent, we
80 // shouldn't either. Besides, drawing a focus frame around an unknown
81 // item without any way to turn it off can easily be unwanted. A better
82 // way for custom controls to get a native focus frame is for us to offer
83 // a FocusFrame control (QTBUG-86818).
85 }
86
87 // If the control gives us a QQuickStyleItem, we use that to configure the focus frame.
88 // By default we assume that the background delegate is a QQuickStyleItem, but the
89 // control can override this by setting __focusFrameStyleItem.
90 const auto styleItemProperty = control->property("__focusFrameStyleItem");
91 auto item = styleItemProperty.value<QQuickItem *>();
92 if (!item) {
93 const auto styleItemProperty = control->property("background");
94 item = styleItemProperty.value<QQuickItem *>();
95 }
96 qCDebug(lcFocusFrame) << "styleItem:" << item;
97 if (!item)
99 if (QQuickStyleItem *styleItem = qobject_cast<QQuickStyleItem *>(item))
100 return { target, QQuickStyleMargins(styleItem->layoutMargins()), styleItem->focusFrameRadius() };
101
102 // Some controls don't have a QQuickStyleItem. But if the __focusFrameStyleItem
103 // has a "__focusFrameRadius" property set, we show a default focus frame using the specified radius instead.
104 const QVariant focusFrameRadiusVariant = item->property("__focusFrameRadius");
105 if (focusFrameRadiusVariant.isValid()) {
106 qCDebug(lcFocusFrame) << "'focusFrameRadius' property found, showing a default focus frame";
107 const QStyleOption opt;
108 const qreal radius = qMax(0.0, focusFrameRadiusVariant.toReal());
109 return { target, QQuickStyleMargins(), radius };
110 }
111
112 // The application has set a custom delegate on the control. In that
113 // case, it's the delegates responsibility to draw a focus frame.
114 qCDebug(lcFocusFrame) << "custom delegates in use, skip showing focus frame";
116}
117
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:2960
QVariant property(const char *name) const
Returns the value of the object's name property.
Definition qobject.cpp:4323
static QQmlContext * contextForObject(const QObject *)
Returns the QQmlContext for the object, or nullptr if no context has been set.
virtual QQuickItem * createFocusFrame(QQmlContext *context)=0
The QQuickItem class provides the most basic of all visual items in \l {Qt Quick}.
Definition qquickitem.h:63
QQuickItem * parentItem() const
The QStyleOption class stores the parameters used by QStyle functions.
\inmodule QtCore
Definition qvariant.h:65
T value() const &
Definition qvariant.h:516
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:536
QStyleOptionButton opt
Combined button and popup list for selecting options.
static void * context
EGLConfig config
#define qGuiApp
#define qWarning
Definition qlogging.h:166
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
@ Invalid
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
#define Q_ARG(Type, data)
Definition qobjectdefs.h:63
GLenum target
double qreal
Definition qtypes.h:187
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