diff options
author | Robert Griebl <robert.griebl@qt.io> | 2023-09-25 21:44:43 +0200 |
---|---|---|
committer | Robert Griebl <robert.griebl@qt.io> | 2023-11-06 15:17:37 +0100 |
commit | ca4215d582b87686cf9aafe0f51c9c98db96bb8c (patch) | |
tree | ffb61926782f1cd9447cac06265d1dcb26593c7a | |
parent | 25e73aae0935c87e69d89371d2018f8bbfa1e3f6 (diff) |
Add an ApplicationManagerWindow attached object
This makes it easier to always reach your AMW instance, especially now
in multi-process mode, where Window.window will NOT be the AMW anymore.
The attached object is modelled after the Window attached one, so
activeFocusItem was added to both AMW and AMWAttached.
Also fixed the most obvious of the non-implemented in-process AMW
properties. This needs a follow-up commit to completely fix that
though.
Change-Id: Icac9bfb2994ca6250f0056e142bd59c8ef4b469a
Task-number: QTBUG-103266
Reviewed-by: Bernd Weimer <bernd.weimer@qt.io>
-rw-r--r-- | qmltypes/QtApplicationManager/Application/plugins.qmltypes | 4 | ||||
-rw-r--r-- | src/application-main-lib/applicationmain.cpp | 4 | ||||
-rw-r--r-- | src/application-main-lib/waylandapplicationmanagerwindowimpl.cpp | 40 | ||||
-rw-r--r-- | src/application-main-lib/waylandapplicationmanagerwindowimpl.h | 11 | ||||
-rw-r--r-- | src/manager-lib/inprocesssurfaceitem.cpp | 11 | ||||
-rw-r--r-- | src/manager-lib/inprocesssurfaceitem.h | 8 | ||||
-rw-r--r-- | src/manager-lib/qmlinprocapplicationmanagerwindowimpl.cpp | 143 | ||||
-rw-r--r-- | src/manager-lib/qmlinprocapplicationmanagerwindowimpl.h | 40 | ||||
-rw-r--r-- | src/shared-main-lib/applicationmanagerwindow.cpp | 89 | ||||
-rw-r--r-- | src/shared-main-lib/applicationmanagerwindow.h | 58 | ||||
-rw-r--r-- | src/shared-main-lib/applicationmanagerwindowimpl.cpp | 40 | ||||
-rw-r--r-- | src/shared-main-lib/applicationmanagerwindowimpl.h | 32 | ||||
-rw-r--r-- | src/window-lib/windowmanager.cpp | 4 |
13 files changed, 457 insertions, 27 deletions
diff --git a/qmltypes/QtApplicationManager/Application/plugins.qmltypes b/qmltypes/QtApplicationManager/Application/plugins.qmltypes index 452854c1..3c4af941 100644 --- a/qmltypes/QtApplicationManager/Application/plugins.qmltypes +++ b/qmltypes/QtApplicationManager/Application/plugins.qmltypes @@ -36,6 +36,7 @@ Module { Property { name: "visible"; type: "bool"; isFinal: true } Property { name: "active"; type: "bool"; isReadonly: true; isFinal: true } Property { name: "opacity"; type: "double"; isFinal: true } + Property { name: "activeFocusItem"; type: "QQuickItem"; isPointer: true; isReadonly: true; isFinal: true } Property { name: "data"; type: "QQmlListProperty<QObject>"; isReadonly: true; isFinal: true } Signal { name: "dataChanged" @@ -80,6 +81,9 @@ Module { name: "activeChanged" } Signal { + name: "activeFocusItemChanged" + } + Signal { name: "windowPropertyChanged" Parameter { name: "name"; type: "QString" } Parameter { name: "value"; type: "QVariant" } diff --git a/src/application-main-lib/applicationmain.cpp b/src/application-main-lib/applicationmain.cpp index 32907aa0..a5d6beff 100644 --- a/src/application-main-lib/applicationmain.cpp +++ b/src/application-main-lib/applicationmain.cpp @@ -53,6 +53,10 @@ ApplicationMain::ApplicationMain(int &argc, char **argv) noexcept WaylandApplicationManagerWindowImpl::setFactory([this](ApplicationManagerWindow *window) { return new WaylandApplicationManagerWindowImpl(window, this); }); + WaylandApplicationManagerWindowAttachedImpl::setFactory([](ApplicationManagerWindowAttached *windowAttached, + QQuickItem *attacheeItem) { + return new WaylandApplicationManagerWindowAttachedImpl(windowAttached, attacheeItem); + }); } ApplicationMain::~ApplicationMain() diff --git a/src/application-main-lib/waylandapplicationmanagerwindowimpl.cpp b/src/application-main-lib/waylandapplicationmanagerwindowimpl.cpp index 1d26432b..c1510062 100644 --- a/src/application-main-lib/waylandapplicationmanagerwindowimpl.cpp +++ b/src/application-main-lib/waylandapplicationmanagerwindowimpl.cpp @@ -24,18 +24,21 @@ class AMQuickWindowQmlImpl : public QQuickWindowQmlImpl { Q_OBJECT public: - AMQuickWindowQmlImpl(QWindow *parent) - : QQuickWindowQmlImpl(parent) + AMQuickWindowQmlImpl(ApplicationManagerWindow *amwindow) + : QQuickWindowQmlImpl(nullptr) + , m_amwindow(amwindow) { } using QQuickWindowQmlImpl::classBegin; using QQuickWindowQmlImpl::componentComplete; + + ApplicationManagerWindow *m_amwindow; }; WaylandApplicationManagerWindowImpl::WaylandApplicationManagerWindowImpl(ApplicationManagerWindow *window, ApplicationMain *applicationMain) : ApplicationManagerWindowImpl(window) , m_applicationMain(applicationMain) - , m_qwindow(new AMQuickWindowQmlImpl(nullptr)) + , m_qwindow(new AMQuickWindowQmlImpl(window)) { QObject::connect(m_qwindow, &AMQuickWindowQmlImpl::windowTitleChanged, window, &ApplicationManagerWindow::titleChanged); @@ -63,6 +66,8 @@ WaylandApplicationManagerWindowImpl::WaylandApplicationManagerWindowImpl(Applica window, &ApplicationManagerWindow::colorChanged); QObject::connect(m_qwindow, &AMQuickWindowQmlImpl::activeChanged, window, &ApplicationManagerWindow::activeChanged); + QObject::connect(m_qwindow, &AMQuickWindowQmlImpl::activeFocusItemChanged, + window, &ApplicationManagerWindow::activeFocusItemChanged); } WaylandApplicationManagerWindowImpl::~WaylandApplicationManagerWindowImpl() @@ -296,6 +301,35 @@ bool WaylandApplicationManagerWindowImpl::isActive() const return m_qwindow->isActive(); } +QQuickItem *WaylandApplicationManagerWindowImpl::activeFocusItem() const +{ + return m_qwindow->activeFocusItem(); +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// WaylandApplicationManagerWindowAttachedImpl +/////////////////////////////////////////////////////////////////////////////////////////////////// + + +WaylandApplicationManagerWindowAttachedImpl::WaylandApplicationManagerWindowAttachedImpl(ApplicationManagerWindowAttached *windowAttached, QQuickItem *attacheeItem) + : ApplicationManagerWindowAttachedImpl(windowAttached, attacheeItem) +{ } + +ApplicationManagerWindow *WaylandApplicationManagerWindowAttachedImpl::findApplicationManagerWindow() +{ + if (!attacheeItem()) + return nullptr; + + QObject::connect(attacheeItem(), &QQuickItem::windowChanged, + amWindowAttached(), [this](QQuickWindow *newWin) { + auto *quickWindow = qobject_cast<AMQuickWindowQmlImpl *>(newWin); + onWindowChanged(quickWindow ? quickWindow->m_amwindow : nullptr); + }); + auto *quickWindow = qobject_cast<AMQuickWindowQmlImpl *>(attacheeItem()->window()); + return quickWindow ? quickWindow->m_amwindow : nullptr; +} + QT_END_NAMESPACE_AM #include "waylandapplicationmanagerwindowimpl.moc" diff --git a/src/application-main-lib/waylandapplicationmanagerwindowimpl.h b/src/application-main-lib/waylandapplicationmanagerwindowimpl.h index d41e868a..3bcbddc5 100644 --- a/src/application-main-lib/waylandapplicationmanagerwindowimpl.h +++ b/src/application-main-lib/waylandapplicationmanagerwindowimpl.h @@ -56,6 +56,7 @@ public: QColor color() const override; void setColor(const QColor &c) override; bool isActive() const override; + QQuickItem *activeFocusItem() const override; bool setWindowProperty(const QString &name, const QVariant &value) override; QVariant windowProperty(const QString &name) const override; @@ -70,5 +71,15 @@ private: AMQuickWindowQmlImpl *m_qwindow = nullptr; }; + +class WaylandApplicationManagerWindowAttachedImpl : public ApplicationManagerWindowAttachedImpl +{ +public: + WaylandApplicationManagerWindowAttachedImpl(ApplicationManagerWindowAttached *windowAttached, + QQuickItem *attacheeItem); + + ApplicationManagerWindow *findApplicationManagerWindow() override; +}; + QT_END_NAMESPACE_AM // We mean it. Dummy comment since syncqt needs this also for completely private Qt modules. diff --git a/src/manager-lib/inprocesssurfaceitem.cpp b/src/manager-lib/inprocesssurfaceitem.cpp index e18f7ec6..81fb6a25 100644 --- a/src/manager-lib/inprocesssurfaceitem.cpp +++ b/src/manager-lib/inprocesssurfaceitem.cpp @@ -4,6 +4,7 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "inprocesssurfaceitem.h" +#include "applicationmanagerwindow.h" #include <QQmlEngine> #include <QSGSimpleRectNode> @@ -132,6 +133,16 @@ void InProcessSurfaceItem::close() emit closeRequested(); } +ApplicationManagerWindow *InProcessSurfaceItem::applicationManagerWindow() +{ + return m_amWindow.data(); +} + +void InProcessSurfaceItem::setApplicationManagerWindow(ApplicationManagerWindow *win) +{ + m_amWindow = win; +} + QT_END_NAMESPACE_AM #include "moc_inprocesssurfaceitem.cpp" diff --git a/src/manager-lib/inprocesssurfaceitem.h b/src/manager-lib/inprocesssurfaceitem.h index 6600dd8d..03ee0e9d 100644 --- a/src/manager-lib/inprocesssurfaceitem.h +++ b/src/manager-lib/inprocesssurfaceitem.h @@ -16,6 +16,8 @@ QT_BEGIN_NAMESPACE_AM +class ApplicationManagerWindow; + /* * Item exposed to the System UI */ @@ -44,8 +46,8 @@ public: void close(); - QObject *inProcessApplicationManagerWindow() { return m_inProcessAppManWindow.data(); } - void setInProcessApplicationManagerWindow(QObject* win) { m_inProcessAppManWindow = win; } + ApplicationManagerWindow *applicationManagerWindow(); + void setApplicationManagerWindow(ApplicationManagerWindow *win); signals: void visibleClientSideChanged(); @@ -64,7 +66,7 @@ private: QObject m_windowProperties; bool m_visibleClientSide = true; QColor m_color; - QPointer<QObject> m_inProcessAppManWindow; + QPointer<ApplicationManagerWindow> m_amWindow; }; QT_END_NAMESPACE_AM diff --git a/src/manager-lib/qmlinprocapplicationmanagerwindowimpl.cpp b/src/manager-lib/qmlinprocapplicationmanagerwindowimpl.cpp index 046c4195..3467d9e3 100644 --- a/src/manager-lib/qmlinprocapplicationmanagerwindowimpl.cpp +++ b/src/manager-lib/qmlinprocapplicationmanagerwindowimpl.cpp @@ -3,6 +3,9 @@ // Copyright (C) 2018 Pelagicore AG // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only +#include <QQuickWindow> +#include <QtQuick/private/qquickitem_p.h> + #include "logging.h" #include "applicationmanagerwindow.h" #include "qmlinprocapplicationmanagerwindowimpl.h" @@ -10,7 +13,6 @@ #include "qmlinprocruntime.h" #include <private/qqmlcomponentattached_p.h> -#include <QtQuick/private/qquickitem_p.h> QT_BEGIN_NAMESPACE_AM @@ -20,7 +22,7 @@ QmlInProcApplicationManagerWindowImpl::QmlInProcApplicationManagerWindowImpl(App : ApplicationManagerWindowImpl(window) , m_surfaceItem(new InProcessSurfaceItem) { - m_surfaceItem->setInProcessApplicationManagerWindow(window); + m_surfaceItem->setApplicationManagerWindow(window); m_surfaceItem->setColor(QColorConstants::White); QObject::connect(m_surfaceItem.data(), &QQuickItem::widthChanged, @@ -34,6 +36,47 @@ QmlInProcApplicationManagerWindowImpl::QmlInProcApplicationManagerWindowImpl(App QObject::connect(m_surfaceItem.data(), &InProcessSurfaceItem::closeRequested, window, &ApplicationManagerWindow::close); + + if (m_surfaceItem->window()) + connectActiveFocusItem(); + QObject::connect(m_surfaceItem.data(), &InProcessSurfaceItem::windowChanged, + window, [this]() { connectActiveFocusItem(); }); +} +void QmlInProcApplicationManagerWindowImpl::connectActiveFocusItem() +{ + QObject::disconnect(m_activeFocusItemConnection); + + if (m_surfaceItem->window()) { + // We can only track the AFI of our Window directly, but we keep a pointer to the AFI, + // if it is a child of our InProcessSurfaceItem + + m_activeFocusItemConnection = QObject::connect(m_surfaceItem->window(), &QQuickWindow::activeFocusItemChanged, + amWindow(), [this]() { + auto *afi = m_surfaceItem->window() ? m_surfaceItem->window()->activeFocusItem() + : nullptr; + if (afi) { + bool found = false; + QQuickItem *p = afi->parentItem(); + while (p) { + if (p == m_surfaceItem) { + found = true; + break; + } + p = p->parentItem(); + } + if (!found) + afi = nullptr; + } + if (afi != m_activeFocusItem) { + bool activeChanged = (bool(afi) != bool(m_activeFocusItem)); + m_activeFocusItem = afi; + + if (activeChanged) + emit amWindow()->activeChanged(); + emit amWindow()->activeFocusItemChanged(); + } + }); + } } QmlInProcApplicationManagerWindowImpl::~QmlInProcApplicationManagerWindowImpl() @@ -168,22 +211,21 @@ void QmlInProcApplicationManagerWindowImpl::findParentWindow(QObject *object) auto surfaceItem = qobject_cast<InProcessSurfaceItem *>(object); if (surfaceItem) { - setParentWindow(static_cast<ApplicationManagerWindow *>(surfaceItem->inProcessApplicationManagerWindow())); + setParentWindow(surfaceItem->applicationManagerWindow()); } else { - auto inProcessAppWindow = qobject_cast<ApplicationManagerWindow *>(object); - if (inProcessAppWindow) - setParentWindow(inProcessAppWindow); + if (auto window = qobject_cast<ApplicationManagerWindow *>(object)) + setParentWindow(window); else findParentWindow(object->parent()); } } -void QmlInProcApplicationManagerWindowImpl::setParentWindow(ApplicationManagerWindow *inProcessAppWindow) +void QmlInProcApplicationManagerWindowImpl::setParentWindow(ApplicationManagerWindow *newParentWindow) { if (m_parentWindow && m_parentVisibleConnection) QObject::disconnect(m_parentVisibleConnection); - m_parentWindow = inProcessAppWindow; + m_parentWindow = newParentWindow; if (m_parentWindow) { m_parentVisibleConnection = QObject::connect( @@ -223,7 +265,7 @@ int QmlInProcApplicationManagerWindowImpl::width() const void QmlInProcApplicationManagerWindowImpl::setWidth(int w) { - m_surfaceItem->setWidth(w); + m_surfaceItem->setWidth(qBound(m_minimumWidth, w, m_maximumWidth)); } int QmlInProcApplicationManagerWindowImpl::height() const @@ -233,38 +275,58 @@ int QmlInProcApplicationManagerWindowImpl::height() const void QmlInProcApplicationManagerWindowImpl::setHeight(int h) { - m_surfaceItem->setHeight(h); + m_surfaceItem->setHeight(qBound(m_minimumHeight, h, m_maximumHeight)); } void QmlInProcApplicationManagerWindowImpl::setMinimumWidth(int minw) { + if ((minw < 0) || (minw > WindowSizeMax)) + return; + if (m_minimumWidth != minw) { m_minimumWidth = minw; emit amWindow()->minimumWidthChanged(); + if (width() < minw) + setWidth(minw); } } void QmlInProcApplicationManagerWindowImpl::setMinimumHeight(int minh) { + if ((minh < 0) || (minh > WindowSizeMax)) + return; + if (m_minimumHeight != minh) { m_minimumHeight = minh; emit amWindow()->minimumHeightChanged(); + if (height() < minh) + setHeight(minh); } } void QmlInProcApplicationManagerWindowImpl::setMaximumWidth(int maxw) { + if ((maxw < 0) || (maxw > WindowSizeMax)) + return; + if (m_maximumWidth != maxw) { m_maximumWidth = maxw; emit amWindow()->maximumWidthChanged(); + if (width() > maxw) + setWidth(maxw); } } void QmlInProcApplicationManagerWindowImpl::setMaximumHeight(int maxh) { + if ((maxh < 0) || (maxh > WindowSizeMax)) + return; + if (m_maximumHeight != maxh) { m_maximumHeight = maxh; emit amWindow()->maximumHeightChanged(); + if (height() > maxh) + setHeight(maxh); } } @@ -303,4 +365,65 @@ void QmlInProcApplicationManagerWindowImpl::setColor(const QColor &c) } } +bool QmlInProcApplicationManagerWindowImpl::isActive() const +{ + return (m_activeFocusItem); +} + +QQuickItem *QmlInProcApplicationManagerWindowImpl::activeFocusItem() const +{ + return m_activeFocusItem; +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// ApplicationManagerWindowAttached +/////////////////////////////////////////////////////////////////////////////////////////////////// + + +QmlInProcApplicationManagerWindowAttachedImpl::QmlInProcApplicationManagerWindowAttachedImpl(ApplicationManagerWindowAttached *windowAttached, QQuickItem *attacheeItem) + : ApplicationManagerWindowAttachedImpl(windowAttached, attacheeItem) +{ } + +ApplicationManagerWindow *QmlInProcApplicationManagerWindowAttachedImpl::findApplicationManagerWindow() +{ + if (!attacheeItem()) + return nullptr; + + auto ipsurface = findInProcessSurfaceItem(); + return ipsurface ? ipsurface->applicationManagerWindow() : nullptr; +} + +InProcessSurfaceItem *QmlInProcApplicationManagerWindowAttachedImpl::findInProcessSurfaceItem() +{ + // Connect to all parent items' parentChanged() signals, up to root or an InProcessSurfaceItem. + // If one of them changes, disconnect all parentChanged connections, then find the new + // InProcessSurfaceItem and re-connect. + + for (const auto &connection : std::as_const(m_parentChangeConnections)) + QObject::disconnect(connection); + + InProcessSurfaceItem *ipsurface = nullptr; + QQuickItem *p = attacheeItem(); + while (p && !ipsurface) { + ipsurface = qobject_cast<InProcessSurfaceItem *>(p); + if (!ipsurface) { + m_parentChangeConnections << QObject::connect(p, &QQuickItem::parentChanged, + amWindowAttached(), [this]() { onParentChanged(); }); + } + p = p->parentItem(); + } + return ipsurface; +} + +void QmlInProcApplicationManagerWindowAttachedImpl::onParentChanged() +{ + InProcessSurfaceItem *ipsurface = findInProcessSurfaceItem(); + + if (!amWindowAttached()->window() + || (ipsurface != amWindowAttached()->window()->backingObject())) { + onWindowChanged(ipsurface ? ipsurface->applicationManagerWindow() : nullptr); + } +} + QT_END_NAMESPACE_AM diff --git a/src/manager-lib/qmlinprocapplicationmanagerwindowimpl.h b/src/manager-lib/qmlinprocapplicationmanagerwindowimpl.h index 92c24fac..509db596 100644 --- a/src/manager-lib/qmlinprocapplicationmanagerwindowimpl.h +++ b/src/manager-lib/qmlinprocapplicationmanagerwindowimpl.h @@ -58,7 +58,8 @@ public: void setOpacity(qreal opactity) override; QColor color() const override; void setColor(const QColor &c) override; - bool isActive() const override { return m_active; } + bool isActive() const override; + QQuickItem *activeFocusItem() const override; bool setWindowProperty(const QString &name, const QVariant &value) override; QVariant windowProperty(const QString &name) const override; @@ -72,7 +73,8 @@ private: void notifyRuntimeAboutSurface(); void determineRuntime(); void findParentWindow(QObject *object); - void setParentWindow(ApplicationManagerWindow *inProcessAppWindow); + void setParentWindow(ApplicationManagerWindow *newParentWindow); + void connectActiveFocusItem(); static QVector<QmlInProcApplicationManagerWindowImpl *> s_inCompleteWindows; @@ -81,19 +83,37 @@ private: QVector<QQmlComponentAttached *> m_attachedCompleteHandlers; ApplicationManagerWindow *m_parentWindow = nullptr; QMetaObject::Connection m_parentVisibleConnection; + QMetaObject::Connection m_activeFocusItemConnection; private: QString m_title; - int m_x; - int m_y; - int m_minimumWidth; - int m_minimumHeight; - int m_maximumWidth; - int m_maximumHeight; - bool m_active; - qreal m_opacity; + int m_x = 0; + int m_y = 0; + int m_minimumWidth = 0; + int m_minimumHeight = 0; + static const int WindowSizeMax = (1 << 24) - 1; // same as QWINDOWSIZE_MAX + int m_maximumWidth = WindowSizeMax; + int m_maximumHeight = WindowSizeMax; + qreal m_opacity = 1; + QQuickItem *m_activeFocusItem = nullptr; friend class QmlInProcRuntime; // for setting the m_runtime member }; + +class QmlInProcApplicationManagerWindowAttachedImpl : public ApplicationManagerWindowAttachedImpl +{ +public: + QmlInProcApplicationManagerWindowAttachedImpl(ApplicationManagerWindowAttached *windowAttached, + QQuickItem *attacheeItem); + + ApplicationManagerWindow *findApplicationManagerWindow() override; + +private: + void onParentChanged(); + InProcessSurfaceItem *findInProcessSurfaceItem(); + + QVector<QMetaObject::Connection> m_parentChangeConnections; +}; + QT_END_NAMESPACE_AM diff --git a/src/shared-main-lib/applicationmanagerwindow.cpp b/src/shared-main-lib/applicationmanagerwindow.cpp index fd364fb0..b4ee0b44 100644 --- a/src/shared-main-lib/applicationmanagerwindow.cpp +++ b/src/shared-main-lib/applicationmanagerwindow.cpp @@ -80,6 +80,11 @@ ApplicationManagerWindow::~ApplicationManagerWindow() setVisible(false); } +ApplicationManagerWindowAttached *ApplicationManagerWindow::qmlAttachedProperties(QObject *object) +{ + return new ApplicationManagerWindowAttached(object); +} + QQmlListProperty<QObject> ApplicationManagerWindow::data() { return QQmlListProperty<QObject>(this, nullptr, @@ -350,6 +355,90 @@ bool ApplicationManagerWindow::isActive() const return m_impl->isActive(); } +QQuickItem *ApplicationManagerWindow::activeFocusItem() const +{ + return m_impl->activeFocusItem(); +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// ApplicationManagerWindowAttached +/////////////////////////////////////////////////////////////////////////////////////////////////// + + +ApplicationManagerWindowAttached::ApplicationManagerWindowAttached(QObject *attachee) + : QObject(attachee) +{ + if (auto *attacheeItem = qobject_cast<QQuickItem*>(attachee)) { + m_impl.reset(ApplicationManagerWindowAttachedImpl::create(this, attacheeItem)); + + if (auto *amwindow = m_impl->findApplicationManagerWindow()) + reconnect(amwindow); + } +} + + +void ApplicationManagerWindowAttached::reconnect(ApplicationManagerWindow *newWin) +{ + if (newWin == m_amwindow) + return; + + if (m_amwindow) + QObject::disconnect(m_amwindow, nullptr, this, nullptr); + + m_amwindow = newWin; + emit windowChanged(); + emit backingObjectChanged(); + emit contentItemChanged(); + + if (m_amwindow) { + QObject::connect(m_amwindow, &ApplicationManagerWindow::activeChanged, + this, &ApplicationManagerWindowAttached::activeChanged); + QObject::connect(m_amwindow, &ApplicationManagerWindow::activeFocusItemChanged, + this, &ApplicationManagerWindowAttached::activeFocusItemChanged); + QObject::connect(m_amwindow, &ApplicationManagerWindow::widthChanged, + this, &ApplicationManagerWindowAttached::widthChanged); + QObject::connect(m_amwindow, &ApplicationManagerWindow::heightChanged, + this, &ApplicationManagerWindowAttached::heightChanged); + } +} + +ApplicationManagerWindow *ApplicationManagerWindowAttached::window() const +{ + return m_amwindow.get(); +} + +QObject *ApplicationManagerWindowAttached::backingObject() const +{ + return m_amwindow ? m_amwindow->backingObject() : nullptr; +} + +bool ApplicationManagerWindowAttached::isActive() const +{ + return m_amwindow ? m_amwindow->isActive() : false; +} + +QQuickItem *ApplicationManagerWindowAttached::activeFocusItem() const +{ + return m_amwindow ? m_amwindow->activeFocusItem() : nullptr; +} + +QQuickItem *ApplicationManagerWindowAttached::contentItem() const +{ + return m_amwindow ? m_amwindow->contentItem() : nullptr; +} + +int ApplicationManagerWindowAttached::width() const +{ + return m_amwindow ? m_amwindow->height() : 0; +} + +int ApplicationManagerWindowAttached::height() const +{ + return m_amwindow ? m_amwindow->height() : 0; +} + + QT_END_NAMESPACE_AM #include "moc_applicationmanagerwindow.cpp" diff --git a/src/shared-main-lib/applicationmanagerwindow.h b/src/shared-main-lib/applicationmanagerwindow.h index ea6ebb87..a41f7d05 100644 --- a/src/shared-main-lib/applicationmanagerwindow.h +++ b/src/shared-main-lib/applicationmanagerwindow.h @@ -10,6 +10,7 @@ #include <QtGui/QColor> #include <QtQml/QQmlParserStatus> #include <QtQml/QQmlListProperty> +#include <QtQml/QQmlEngine> #include <QtAppManCommon/global.h> @@ -19,6 +20,8 @@ QT_FORWARD_DECLARE_CLASS(QQuickItem) QT_BEGIN_NAMESPACE_AM class ApplicationManagerWindowImpl; +class ApplicationManagerWindowAttached; +class ApplicationManagerWindowAttachedImpl; class ApplicationManagerWindow : public QObject, public QQmlParserStatus @@ -26,10 +29,11 @@ class ApplicationManagerWindow : public QObject, public QQmlParserStatus Q_OBJECT Q_CLASSINFO("AM-QmlType", "QtApplicationManager.Application/ApplicationManagerWindow 2.0") Q_INTERFACES(QQmlParserStatus) + QML_ATTACHED(ApplicationManagerWindowAttached) Q_PROPERTY(bool inProcess READ isInProcess CONSTANT FINAL) Q_PROPERTY(QObject *backingObject READ backingObject CONSTANT FINAL) Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged FINAL) - Q_PROPERTY(QQuickItem* contentItem READ contentItem CONSTANT FINAL) + Q_PROPERTY(QQuickItem *contentItem READ contentItem CONSTANT FINAL) // QWindow properties Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged FINAL) @@ -48,6 +52,7 @@ class ApplicationManagerWindow : public QObject, public QQmlParserStatus //Q_PROPERTY(Visibility visibility READ visibility WRITE setVisibility NOTIFY visibilityChanged FINAL) //Q_PROPERTY(Qt::ScreenOrientation contentOrientation READ contentOrientation WRITE reportContentOrientationChange NOTIFY contentOrientationChanged FINAL) Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity NOTIFY opacityChanged FINAL) + Q_PROPERTY(QQuickItem *activeFocusItem READ activeFocusItem NOTIFY activeFocusItemChanged FINAL) Q_PROPERTY(QQmlListProperty<QObject> data READ data NOTIFY dataChanged FINAL) @@ -57,6 +62,8 @@ public: explicit ApplicationManagerWindow(QObject *parent = nullptr); ~ApplicationManagerWindow() override; + static ApplicationManagerWindowAttached *qmlAttachedProperties(QObject *object); + bool isInProcess() const; QObject *backingObject() const; @@ -106,6 +113,8 @@ public: Q_SIGNAL void colorChanged(); bool isActive() const; Q_SIGNAL void activeChanged(); + QQuickItem *activeFocusItem() const; + Q_SIGNAL void activeFocusItemChanged(); Q_INVOKABLE bool setWindowProperty(const QString &name, const QVariant &value); Q_INVOKABLE QVariant windowProperty(const QString &name) const; @@ -134,6 +143,53 @@ private: static qsizetype data_count(QQmlListProperty<QObject> *property); static QObject *data_at(QQmlListProperty<QObject> *property, qsizetype index); static void data_clear(QQmlListProperty<QObject> *property); + + Q_DISABLE_COPY_MOVE(ApplicationManagerWindow) }; +class ApplicationManagerWindowAttached : public QObject +{ + Q_OBJECT + QML_ANONYMOUS + Q_PROPERTY(ApplicationManagerWindow *window READ window NOTIFY windowChanged FINAL) + Q_PROPERTY(QObject *backingObject READ backingObject NOTIFY backingObjectChanged FINAL) +// Q_PROPERTY(QWindow::Visibility visibility READ visibility NOTIFY visibilityChanged FINAL) + Q_PROPERTY(bool active READ isActive NOTIFY activeChanged FINAL) + Q_PROPERTY(QQuickItem *activeFocusItem READ activeFocusItem NOTIFY activeFocusItemChanged FINAL) + Q_PROPERTY(QQuickItem *contentItem READ contentItem NOTIFY contentItemChanged FINAL) + Q_PROPERTY(int width READ width NOTIFY widthChanged FINAL) + Q_PROPERTY(int height READ height NOTIFY heightChanged FINAL) + +public: + explicit ApplicationManagerWindowAttached(QObject *attachee); + + ApplicationManagerWindow *window() const; + Q_SIGNAL void windowChanged(); + QObject *backingObject() const; + Q_SIGNAL void backingObjectChanged(); +// QWindow::Visibility visibility() const; +// Q_SIGNAL void visibilityChanged(); + bool isActive() const; + Q_SIGNAL void activeChanged(); + QQuickItem *activeFocusItem() const; + Q_SIGNAL void activeFocusItemChanged(); + QQuickItem *contentItem() const; + Q_SIGNAL void contentItemChanged(); + int width() const; + Q_SIGNAL void widthChanged(); + int height() const; + Q_SIGNAL void heightChanged(); + + QQuickItem *attachee(); + void reconnect(ApplicationManagerWindow *newWin); // callback for implementation + +protected: + std::unique_ptr<ApplicationManagerWindowAttachedImpl> m_impl; + QPointer<ApplicationManagerWindow> m_amwindow; + +private: + Q_DISABLE_COPY_MOVE(ApplicationManagerWindowAttached) +}; + + QT_END_NAMESPACE_AM diff --git a/src/shared-main-lib/applicationmanagerwindowimpl.cpp b/src/shared-main-lib/applicationmanagerwindowimpl.cpp index f5583ed2..70e0211d 100644 --- a/src/shared-main-lib/applicationmanagerwindowimpl.cpp +++ b/src/shared-main-lib/applicationmanagerwindowimpl.cpp @@ -27,4 +27,44 @@ ApplicationManagerWindow *ApplicationManagerWindowImpl::amWindow() return m_amwindow; } + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// ApplicationManagerWindowAttachedImpl +/////////////////////////////////////////////////////////////////////////////////////////////////// + + +std::function<ApplicationManagerWindowAttachedImpl *(ApplicationManagerWindowAttached *, QQuickItem *)> ApplicationManagerWindowAttachedImpl::s_factory; + +ApplicationManagerWindowAttachedImpl::ApplicationManagerWindowAttachedImpl(ApplicationManagerWindowAttached *windowAttached, + QQuickItem *attacheeItem) + : m_amWindowAttached(windowAttached) + , m_attacheeItem(attacheeItem) +{ } + +void ApplicationManagerWindowAttachedImpl::setFactory(const std::function<ApplicationManagerWindowAttachedImpl *(ApplicationManagerWindowAttached *, QQuickItem *)> &factory) +{ + s_factory = factory; +} + +ApplicationManagerWindowAttachedImpl *ApplicationManagerWindowAttachedImpl::create(ApplicationManagerWindowAttached *windowAttached, QQuickItem *attacheeItem) +{ + return s_factory ? s_factory(windowAttached, attacheeItem) : nullptr; +} + +ApplicationManagerWindowAttached *ApplicationManagerWindowAttachedImpl::amWindowAttached() const +{ + return m_amWindowAttached; +} + +QQuickItem *ApplicationManagerWindowAttachedImpl::attacheeItem() const +{ + return m_attacheeItem; +} + +void ApplicationManagerWindowAttachedImpl::onWindowChanged(ApplicationManagerWindow *newWin) +{ + m_amWindowAttached->reconnect(newWin); +} + + QT_END_NAMESPACE_AM diff --git a/src/shared-main-lib/applicationmanagerwindowimpl.h b/src/shared-main-lib/applicationmanagerwindowimpl.h index 224218e8..a4e56c75 100644 --- a/src/shared-main-lib/applicationmanagerwindowimpl.h +++ b/src/shared-main-lib/applicationmanagerwindowimpl.h @@ -8,10 +8,12 @@ #include <QtAppManCommon/global.h> QT_FORWARD_DECLARE_CLASS(QQuickItem) +QT_FORWARD_DECLARE_CLASS(QQuickWindow) QT_BEGIN_NAMESPACE_AM class ApplicationManagerWindow; +class ApplicationManagerWindowAttached; class ApplicationManagerWindowImpl @@ -59,6 +61,7 @@ public: virtual void setColor(const QColor &c) = 0; virtual bool isActive() const = 0; + virtual QQuickItem *activeFocusItem() const = 0; virtual bool setWindowProperty(const QString &name, const QVariant &value) = 0; virtual QVariant windowProperty(const QString &name) const = 0; @@ -79,4 +82,33 @@ private: Q_DISABLE_COPY_MOVE(ApplicationManagerWindowImpl) }; + +class ApplicationManagerWindowAttachedImpl +{ +public: + static void setFactory(const std::function<ApplicationManagerWindowAttachedImpl *(ApplicationManagerWindowAttached *, QQuickItem *)> &factory); + + static ApplicationManagerWindowAttachedImpl *create(ApplicationManagerWindowAttached *window, + QQuickItem *attacheeItem); + + virtual ~ApplicationManagerWindowAttachedImpl() = default; + + ApplicationManagerWindowAttached *amWindowAttached() const; + QQuickItem *attacheeItem() const; + + virtual ApplicationManagerWindow *findApplicationManagerWindow() = 0; + void onWindowChanged(ApplicationManagerWindow *newWin); + +protected: + ApplicationManagerWindowAttachedImpl(ApplicationManagerWindowAttached *windowAttached, + QQuickItem *attacheeItem); + +private: + ApplicationManagerWindowAttached *m_amWindowAttached; + QQuickItem *m_attacheeItem; + + static std::function<ApplicationManagerWindowAttachedImpl *(ApplicationManagerWindowAttached *, QQuickItem *)> s_factory; + Q_DISABLE_COPY_MOVE(ApplicationManagerWindowAttachedImpl) +}; + QT_END_NAMESPACE_AM diff --git a/src/window-lib/windowmanager.cpp b/src/window-lib/windowmanager.cpp index 5911da01..7c4beee2 100644 --- a/src/window-lib/windowmanager.cpp +++ b/src/window-lib/windowmanager.cpp @@ -229,6 +229,10 @@ WindowManager *WindowManager::createInstance(QQmlEngine *qmlEngine, const QStrin ApplicationManagerWindowImpl::setFactory([](ApplicationManagerWindow *window) { return new QmlInProcApplicationManagerWindowImpl(window); }); + ApplicationManagerWindowAttachedImpl::setFactory([](ApplicationManagerWindowAttached *windowAttached, + QQuickItem *attacheeItem) { + return new QmlInProcApplicationManagerWindowAttachedImpl(windowAttached, attacheeItem); + }); SystemFrameTimerImpl::setFactory([](FrameTimer *frameTimer) { return new SystemFrameTimerImpl(frameTimer); }); |