1// Copyright (C) 2017 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
2// Copyright (C) 2017 The Qt Company Ltd.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
4
5#include "qwaylandquickoutput.h"
6#include "qwaylandquickcompositor.h"
7#include "qwaylandquickitem_p.h"
8
9QT_BEGIN_NAMESPACE
10
11QWaylandQuickOutput::QWaylandQuickOutput()
12{
13}
14
15QWaylandQuickOutput::QWaylandQuickOutput(QWaylandCompositor *compositor, QWindow *window)
16 : QWaylandOutput(compositor, window)
17{
18}
19
20void QWaylandQuickOutput::initialize()
21{
22 QWaylandOutput::initialize();
23
24 QQuickWindow *quickWindow = qobject_cast<QQuickWindow *>(object: window());
25 if (!quickWindow) {
26 qWarning(msg: "Initialization error: Could not locate QQuickWindow on initializing QWaylandQuickOutput %p.\n", this);
27 return;
28 }
29 connect(sender: quickWindow, signal: &QQuickWindow::beforeSynchronizing,
30 context: this, slot: &QWaylandQuickOutput::updateStarted,
31 type: Qt::DirectConnection);
32
33 connect(sender: quickWindow, signal: &QQuickWindow::afterRendering,
34 context: this, slot: &QWaylandQuickOutput::doFrameCallbacks);
35}
36
37void QWaylandQuickOutput::classBegin()
38{
39}
40
41void QWaylandQuickOutput::componentComplete()
42{
43 if (!compositor()) {
44 for (QObject *p = parent(); p != nullptr; p = p->parent()) {
45 if (auto c = qobject_cast<QWaylandCompositor *>(object: p)) {
46 setCompositor(c);
47 break;
48 }
49 }
50 }
51}
52
53void QWaylandQuickOutput::update()
54{
55 if (!m_updateScheduled) {
56 //don't qobject_cast since we have verified the type in initialize
57 static_cast<QQuickWindow *>(window())->update();
58 m_updateScheduled = true;
59 }
60}
61
62/*!
63 * \qmlproperty bool QtWayland.Compositor::WaylandOutput::automaticFrameCallback
64 *
65 * This property holds whether the WaylandOutput automatically sends frame
66 * callbacks when rendering.
67 *
68 * The default is true.
69 */
70bool QWaylandQuickOutput::automaticFrameCallback() const
71{
72 return m_automaticFrameCallback;
73}
74
75void QWaylandQuickOutput::setAutomaticFrameCallback(bool automatic)
76{
77 if (m_automaticFrameCallback == automatic)
78 return;
79
80 m_automaticFrameCallback = automatic;
81 automaticFrameCallbackChanged();
82}
83
84static QQuickItem* clickableItemAtPosition(QQuickItem *rootItem, const QPointF &position)
85{
86 if (!rootItem->isEnabled() || !rootItem->isVisible())
87 return nullptr;
88
89 QList<QQuickItem *> paintOrderItems = QQuickItemPrivate::get(item: rootItem)->paintOrderChildItems();
90 auto negativeZStart = paintOrderItems.crend();
91 for (auto it = paintOrderItems.crbegin(); it != paintOrderItems.crend(); ++it) {
92 if ((*it)->z() < 0) {
93 negativeZStart = it;
94 break;
95 }
96 QQuickItem *item = clickableItemAtPosition(rootItem: *it, position: rootItem->mapToItem(item: *it, point: position));
97 if (item)
98 return item;
99 }
100
101 if (rootItem->contains(point: position) && rootItem->acceptedMouseButtons() != Qt::NoButton)
102 return rootItem;
103
104 for (auto it = negativeZStart; it != paintOrderItems.crend(); ++it) {
105 QQuickItem *item = clickableItemAtPosition(rootItem: *it, position: rootItem->mapToItem(item: *it, point: position));
106 if (item)
107 return item;
108 }
109
110 return nullptr;
111}
112
113QQuickItem *QWaylandQuickOutput::pickClickableItem(const QPointF &position)
114{
115 QQuickWindow *quickWindow = qobject_cast<QQuickWindow *>(object: window());
116 if (!quickWindow)
117 return nullptr;
118
119 return clickableItemAtPosition(rootItem: quickWindow->contentItem(), position);
120}
121
122/*!
123 * \internal
124 */
125void QWaylandQuickOutput::updateStarted()
126{
127 m_updateScheduled = false;
128
129 if (!compositor())
130 return;
131
132 frameStarted();
133}
134
135void QWaylandQuickOutput::doFrameCallbacks()
136{
137 if (m_automaticFrameCallback)
138 sendFrameCallbacks();
139}
140QT_END_NAMESPACE
141
142#include "moc_qwaylandquickoutput.cpp"
143

source code of qtwayland/src/compositor/compositor_api/qwaylandquickoutput.cpp