1/****************************************************************************
2**
3** Copyright (C) 2017 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
4** Copyright (C) 2017 The Qt Company Ltd.
5** Contact: https://www.qt.io/licensing/
6**
7** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:GPL$
10** Commercial License Usage
11** Licensees holding valid commercial Qt licenses may use this file in
12** accordance with the commercial license agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and The Qt Company. For licensing terms
15** and conditions see https://www.qt.io/terms-conditions. For further
16** information use the contact form at https://www.qt.io/contact-us.
17**
18** GNU General Public License Usage
19** Alternatively, this file may be used under the terms of the GNU
20** General Public License version 3 or (at your option) any later version
21** approved by the KDE Free Qt Foundation. The licenses are as published by
22** the Free Software Foundation and appearing in the file LICENSE.GPL3
23** included in the packaging of this file. Please review the following
24** information to ensure the GNU General Public License requirements will
25** be met: https://www.gnu.org/licenses/gpl-3.0.html.
26**
27** $QT_END_LICENSE$
28**
29****************************************************************************/
30
31#include "qwaylandquickoutput.h"
32#include "qwaylandquickcompositor.h"
33#include "qwaylandquickitem_p.h"
34
35QT_BEGIN_NAMESPACE
36
37QWaylandQuickOutput::QWaylandQuickOutput()
38{
39}
40
41QWaylandQuickOutput::QWaylandQuickOutput(QWaylandCompositor *compositor, QWindow *window)
42 : QWaylandOutput(compositor, window)
43{
44}
45
46void QWaylandQuickOutput::initialize()
47{
48 QWaylandOutput::initialize();
49
50 QQuickWindow *quickWindow = qobject_cast<QQuickWindow *>(object: window());
51 if (!quickWindow) {
52 qWarning(msg: "Initialization error: Could not locate QQuickWindow on initializing QWaylandQuickOutput %p.\n", this);
53 return;
54 }
55 connect(sender: quickWindow, signal: &QQuickWindow::beforeSynchronizing,
56 receiver: this, slot: &QWaylandQuickOutput::updateStarted,
57 type: Qt::DirectConnection);
58
59 connect(sender: quickWindow, signal: &QQuickWindow::afterRendering,
60 receiver: this, slot: &QWaylandQuickOutput::doFrameCallbacks);
61}
62
63void QWaylandQuickOutput::classBegin()
64{
65}
66
67void QWaylandQuickOutput::componentComplete()
68{
69 if (!compositor()) {
70 for (QObject *p = parent(); p != nullptr; p = p->parent()) {
71 if (auto c = qobject_cast<QWaylandCompositor *>(object: p)) {
72 setCompositor(c);
73 break;
74 }
75 }
76 }
77}
78
79void QWaylandQuickOutput::update()
80{
81 if (!m_updateScheduled) {
82 //don't qobject_cast since we have verified the type in initialize
83 static_cast<QQuickWindow *>(window())->update();
84 m_updateScheduled = true;
85 }
86}
87
88/*!
89 * \qmlproperty bool QtWaylandCompositor::WaylandOutput::automaticFrameCallback
90 *
91 * This property holds whether the WaylandOutput automatically sends frame
92 * callbacks when rendering.
93 *
94 * The default is true.
95 */
96bool QWaylandQuickOutput::automaticFrameCallback() const
97{
98 return m_automaticFrameCallback;
99}
100
101void QWaylandQuickOutput::setAutomaticFrameCallback(bool automatic)
102{
103 if (m_automaticFrameCallback == automatic)
104 return;
105
106 m_automaticFrameCallback = automatic;
107 automaticFrameCallbackChanged();
108}
109
110static QQuickItem* clickableItemAtPosition(QQuickItem *rootItem, const QPointF &position)
111{
112 if (!rootItem->isEnabled() || !rootItem->isVisible())
113 return nullptr;
114
115 QList<QQuickItem *> paintOrderItems = QQuickItemPrivate::get(item: rootItem)->paintOrderChildItems();
116 auto negativeZStart = paintOrderItems.crend();
117 for (auto it = paintOrderItems.crbegin(); it != paintOrderItems.crend(); ++it) {
118 if ((*it)->z() < 0) {
119 negativeZStart = it;
120 break;
121 }
122 QQuickItem *item = clickableItemAtPosition(rootItem: *it, position: rootItem->mapToItem(item: *it, point: position));
123 if (item)
124 return item;
125 }
126
127 if (rootItem->contains(point: position) && rootItem->acceptedMouseButtons() != Qt::NoButton)
128 return rootItem;
129
130 for (auto it = negativeZStart; it != paintOrderItems.crend(); ++it) {
131 QQuickItem *item = clickableItemAtPosition(rootItem: *it, position: rootItem->mapToItem(item: *it, point: position));
132 if (item)
133 return item;
134 }
135
136 return nullptr;
137}
138
139QQuickItem *QWaylandQuickOutput::pickClickableItem(const QPointF &position)
140{
141 QQuickWindow *quickWindow = qobject_cast<QQuickWindow *>(object: window());
142 if (!quickWindow)
143 return nullptr;
144
145 return clickableItemAtPosition(rootItem: quickWindow->contentItem(), position);
146}
147
148/*!
149 * \internal
150 */
151void QWaylandQuickOutput::updateStarted()
152{
153 m_updateScheduled = false;
154
155 if (!compositor())
156 return;
157
158 frameStarted();
159}
160
161void QWaylandQuickOutput::doFrameCallbacks()
162{
163 if (m_automaticFrameCallback)
164 sendFrameCallbacks();
165}
166QT_END_NAMESPACE
167

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