blob: 60ca7c49c28f4c1f5241e48360d60d3362381be2 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
|
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
// Qt-Security score:significant reason:default
#include "qquickfluentwinui3focusframe_p.h"
#include <private/qquickitem_p.h>
#include <QtCore/qmetaobject.h>
#include <QtGui/qguiapplication.h>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcontext.h>
#include <QtQml/qqmlcomponent.h>
QT_BEGIN_NAMESPACE
QScopedPointer<QQuickItem> QQuickFluentWinUI3FocusFrame::m_focusFrame;
QQuickFluentWinUI3FocusFrame::QQuickFluentWinUI3FocusFrame()
{
connect(qGuiApp, &QGuiApplication::focusObjectChanged, this, [this](QObject *focusObject){
if (QQuickControl *control = qobject_cast<QQuickControl *>(focusObject);
control && (control->focusReason() == Qt::FocusReason::TabFocusReason
|| control->focusReason() == Qt::FocusReason::BacktabFocusReason
|| control->focusReason() == Qt::FocusReason::OtherFocusReason)) {
moveToItem(control);
} else {
moveToItem(nullptr);
}
});
}
QQuickItem *QQuickFluentWinUI3FocusFrame::createFocusFrame(QQmlContext *context)
{
QQmlComponent component(context->engine(), "QtQuick.Controls.FluentWinUI3.impl", "FocusFrame");
auto frame = qobject_cast<QQuickItem *>(component.create());
if (!frame)
return nullptr;
return frame;
}
void QQuickFluentWinUI3FocusFrame::moveToItem(QQuickControl *item)
{
if (!m_focusFrame) {
const auto context = QQmlEngine::contextForObject(item);
// In certain cases like QQuickWebEngineView, the item
// gets focus even though it has no QQmlEngine associated with its context.
// We need the engine for creating the focus frame component.
if (!context || !context->engine())
return;
m_focusFrame.reset(createFocusFrame(context));
if (!m_focusFrame) {
qWarning() << "Failed to create FocusFrame";
return;
}
QQuickItemPrivate::get(m_focusFrame.get())->setTransparentForPositioner(true);
}
const auto target = getFocusTarget(item);
QMetaObject::invokeMethod(m_focusFrame.data(), "moveToItem",
Q_ARG(QVariant, QVariant::fromValue(target)));
}
QQuickControl *QQuickFluentWinUI3FocusFrame::getFocusTarget(QQuickControl *focusItem) const
{
if (!focusItem)
return nullptr;
const auto parentItem = focusItem->parentItem();
if (!parentItem)
return nullptr;
// The control that gets active focus can be a child of the control (e.g
// editable ComboBox). In that case, resolve the actual control first.
const auto proxy = focusItem->property("__focusFrameControl").value<QQuickControl *>();
const auto control = proxy ? proxy : focusItem;
auto target = control->property("__focusFrameTarget").value<QQuickControl *>();
return target;
}
QT_END_NAMESPACE
#include "moc_qquickfluentwinui3focusframe_p.cpp"
|