// 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 #include #include #include #include #include QT_BEGIN_NAMESPACE QScopedPointer QQuickFluentWinUI3FocusFrame::m_focusFrame; QQuickFluentWinUI3FocusFrame::QQuickFluentWinUI3FocusFrame() { connect(qGuiApp, &QGuiApplication::focusObjectChanged, this, [this](QObject *focusObject){ if (QQuickControl *control = qobject_cast(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(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(); const auto control = proxy ? proxy : focusItem; auto target = control->property("__focusFrameTarget").value(); return target; } QT_END_NAMESPACE #include "moc_qquickfluentwinui3focusframe_p.cpp"