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 | |
35 | QT_BEGIN_NAMESPACE |
36 | |
37 | QWaylandQuickOutput::QWaylandQuickOutput() |
38 | { |
39 | } |
40 | |
41 | QWaylandQuickOutput::QWaylandQuickOutput(QWaylandCompositor *compositor, QWindow *window) |
42 | : QWaylandOutput(compositor, window) |
43 | { |
44 | } |
45 | |
46 | void 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 | |
63 | void QWaylandQuickOutput::classBegin() |
64 | { |
65 | } |
66 | |
67 | void 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 | |
79 | void 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 | */ |
96 | bool QWaylandQuickOutput::automaticFrameCallback() const |
97 | { |
98 | return m_automaticFrameCallback; |
99 | } |
100 | |
101 | void QWaylandQuickOutput::setAutomaticFrameCallback(bool automatic) |
102 | { |
103 | if (m_automaticFrameCallback == automatic) |
104 | return; |
105 | |
106 | m_automaticFrameCallback = automatic; |
107 | automaticFrameCallbackChanged(); |
108 | } |
109 | |
110 | static 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 | |
139 | QQuickItem *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 | */ |
151 | void QWaylandQuickOutput::updateStarted() |
152 | { |
153 | m_updateScheduled = false; |
154 | |
155 | if (!compositor()) |
156 | return; |
157 | |
158 | frameStarted(); |
159 | } |
160 | |
161 | void QWaylandQuickOutput::doFrameCallbacks() |
162 | { |
163 | if (m_automaticFrameCallback) |
164 | sendFrameCallbacks(); |
165 | } |
166 | QT_END_NAMESPACE |
167 | |