on 34be00a help sign in
unity8/tests/mocks/Unity/Application/MirSurfaceItem.cpp
387 lines 11 kB history raw
1/*
2 * Copyright (C) 2014-2016 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
17#include "MirSurfaceItem.h"
19#include <paths.h>
21#include <QGuiApplication>
22#include <QQuickView>
23#include <QQmlContext>
24#include <QQmlProperty>
25#include <QQmlEngine>
26#include <QString>
28#include <QDebug>
30using namespace unity::shell::application;
32#define MIRSURFACEITEM_DEBUG 0
34#if MIRSURFACEITEM_DEBUG
35#define DEBUG_MSG(params) qDebug().nospace() << "MirSurfaceItem::" << __func__ << " " << params
36#else
37#define DEBUG_MSG(params) ((void)0)
38#endif
40MirSurfaceItem::MirSurfaceItem(QQuickItem *parent)
41 : MirSurfaceItemInterface(parent)
42 , m_qmlSurface(nullptr)
43 , m_qmlContentComponent(nullptr)
44 , m_qmlItem(nullptr)
45 , m_consumesInput(false)
46 , m_orientationAngle(nullptr)
47 , m_surfaceWidth(0)
48 , m_surfaceHeight(0)
49 , m_touchPressCount(0)
50 , m_touchReleaseCount(0)
51 , m_mousePressCount(0)
52 , m_mouseReleaseCount(0)
54 DEBUG_MSG((void*)(this) << name());
55 setAcceptedMouseButtons(Qt::LeftButton | Qt::MiddleButton | Qt::RightButton |
56 Qt::ExtraButton1 | Qt::ExtraButton2 | Qt::ExtraButton3 | Qt::ExtraButton4 |
57 Qt::ExtraButton5 | Qt::ExtraButton6 | Qt::ExtraButton7 | Qt::ExtraButton8 |
58 Qt::ExtraButton9 | Qt::ExtraButton10 | Qt::ExtraButton11 |
59 Qt::ExtraButton12 | Qt::ExtraButton13);
61 connect(this, &QQuickItem::activeFocusChanged, this, &MirSurfaceItem::updateMirSurfaceActiveFocus);
62 connect(this, &QQuickItem::visibleChanged, this, &MirSurfaceItem::updateMirSurfaceVisibility);
63 connect(this, &MirSurfaceItem::consumesInputChanged, this, [this]() {
64 updateMirSurfaceActiveFocus(hasActiveFocus());
65 });
68MirSurfaceItem::~MirSurfaceItem()
70 DEBUG_MSG((void*)(this) << name());
71 setSurface(nullptr);
72 delete m_orientationAngle;
75void MirSurfaceItem::printComponentErrors()
77 QList<QQmlError> errors = m_qmlContentComponent->errors();
78 for (int i = 0; i < errors.count(); ++i) {
79 qDebug() << errors[i];
80 }
83Mir::Type MirSurfaceItem::type() const
85 if (m_qmlSurface) {
86 return m_qmlSurface->type();
87 } else {
88 return Mir::UnknownType;
89 }
92Mir::State MirSurfaceItem::surfaceState() const
94 if (m_qmlSurface) {
95 return m_qmlSurface->state();
96 } else {
97 return Mir::UnknownState;
98 }
101QString MirSurfaceItem::name() const
103 if (m_qmlSurface) {
104 return m_qmlSurface->name();
105 } else {
106 return QString();
107 }
110bool MirSurfaceItem::live() const
112 if (m_qmlSurface) {
113 return m_qmlSurface->live();
114 } else {
115 return false;
116 }
119Mir::ShellChrome MirSurfaceItem::shellChrome() const
121 if (m_qmlSurface) {
122 return m_qmlSurface->shellChrome();
123 } else {
124 return Mir::NormalChrome;
125 }
128Mir::OrientationAngle MirSurfaceItem::orientationAngle() const
130 if (m_orientationAngle) {
131 Q_ASSERT(!m_qmlSurface);
132 return *m_orientationAngle;
133 } else if (m_qmlSurface) {
134 return m_qmlSurface->orientationAngle();
135 } else {
136 return Mir::Angle0;
137 }
140void MirSurfaceItem::setOrientationAngle(Mir::OrientationAngle angle)
142 DEBUG_MSG(angle);
144 if (m_qmlSurface) {
145 Q_ASSERT(!m_orientationAngle);
146 m_qmlSurface->setOrientationAngle(angle);
147 } else if (!m_orientationAngle) {
148 m_orientationAngle = new Mir::OrientationAngle;
149 *m_orientationAngle = angle;
150 Q_EMIT orientationAngleChanged(angle);
151 } else if (*m_orientationAngle != angle) {
152 *m_orientationAngle = angle;
153 Q_EMIT orientationAngleChanged(angle);
154 }
156 if (m_qmlItem) {
157 QQmlProperty orientationProp(m_qmlItem, "orientationAngle");
158 orientationProp.write(QVariant::fromValue(orientationAngle()));
159 }
162void MirSurfaceItem::updateScreenshot(QUrl screenshotUrl)
164 if (m_qmlItem) {
165 QQmlProperty screenshotSource(m_qmlItem, "screenshotSource");
166 screenshotSource.write(QVariant::fromValue(screenshotUrl));
167 }
170void MirSurfaceItem::onComponentStatusChanged(QQmlComponent::Status status)
172 if (status == QQmlComponent::Ready) {
173 createQmlContentItem();
174 }
177void MirSurfaceItem::createQmlContentItem()
179 DEBUG_MSG("");
181 m_qmlItem = qobject_cast<QQuickItem*>(m_qmlContentComponent->create());
182 m_qmlItem->setParentItem(this);
184 setImplicitWidth(m_qmlItem->implicitWidth());
185 setImplicitHeight(m_qmlItem->implicitHeight());
187 {
188 QQmlProperty screenshotSource(m_qmlItem, "screenshotSource");
189 screenshotSource.write(QVariant::fromValue(m_qmlSurface->screenshotUrl()));
190 }
192 {
193 QQmlProperty orientationProp(m_qmlItem, "orientationAngle");
194 orientationProp.write(QVariant::fromValue(orientationAngle()));
195 }
198void MirSurfaceItem::touchEvent(QTouchEvent * event)
200 if (event->type() == QEvent::TouchBegin) {
201 m_touchTrail.clear();
202 }
204 if (event->touchPointStates() & Qt::TouchPointPressed) {
205 ++m_touchPressCount;
206 Q_EMIT touchPressCountChanged(m_touchPressCount);
207 } else if (event->touchPointStates() & Qt::TouchPointReleased) {
208 ++m_touchReleaseCount;
209 Q_EMIT touchReleaseCountChanged(m_touchReleaseCount);
210 }
212 Q_FOREACH(QTouchEvent::TouchPoint touchPoint, event->touchPoints()) {
213 QString id(touchPoint.id());
214 QVariantList list = m_touchTrail[id].toList();
215 list.append(QVariant::fromValue(touchPoint.pos()));
216 if (list.count() > 100) list.pop_front();
217 m_touchTrail[id] = list;
218 }
220 if (m_qmlItem) {
221 QQmlProperty touchTrail(m_qmlItem, "touchTrail");
222 touchTrail.write(m_touchTrail);
223 }
226void MirSurfaceItem::mousePressEvent(QMouseEvent * event)
228 m_mousePressCount++;
229 Q_EMIT mousePressCountChanged(m_mousePressCount);
230 event->accept();
233void MirSurfaceItem::mouseMoveEvent(QMouseEvent * event)
235 event->accept();
238void MirSurfaceItem::mouseReleaseEvent(QMouseEvent * event)
240 m_mouseReleaseCount++;
241 Q_EMIT mouseReleaseCountChanged(m_mouseReleaseCount);
242 event->accept();
245void MirSurfaceItem::setSurface(MirSurfaceInterface* surface)
247 DEBUG_MSG("this=" << (void*)(this) << " name=" << name() << " surface=" << surface);
249 if (m_qmlSurface == surface) {
250 return;
251 }
253 if (m_qmlSurface) {
254 delete m_qmlItem;
255 m_qmlItem = nullptr;
257 delete m_qmlContentComponent;
258 m_qmlContentComponent = nullptr;
260 if (hasActiveFocus() && m_consumesInput && m_qmlSurface->live()) {
261 m_qmlSurface->setActiveFocus(false);
262 }
264 disconnect(m_qmlSurface, nullptr, this, nullptr);
265 m_qmlSurface->unregisterView((qintptr)this);
266 }
268 m_qmlSurface = static_cast<MirSurface*>(surface);
270 if (m_qmlSurface) {
271 m_qmlSurface->registerView((qintptr)this);
273 updateSurfaceSize();
274 updateMirSurfaceVisibility();
276 if (m_orientationAngle) {
277 m_qmlSurface->setOrientationAngle(*m_orientationAngle);
278 connect(m_qmlSurface, &MirSurfaceInterface::orientationAngleChanged, this, &MirSurfaceItem::orientationAngleChanged);
279 delete m_orientationAngle;
280 m_orientationAngle = nullptr;
281 } else {
282 connect(m_qmlSurface, &MirSurfaceInterface::orientationAngleChanged, this, &MirSurfaceItem::orientationAngleChanged);
283 Q_EMIT orientationAngleChanged(m_qmlSurface->orientationAngle());
284 }
286 connect(m_qmlSurface, &MirSurface::screenshotUrlChanged, this, &MirSurfaceItem::updateScreenshot);
287 connect(m_qmlSurface, &MirSurface::liveChanged, this, &MirSurfaceItem::liveChanged);
288 connect(m_qmlSurface, &MirSurface::stateChanged, this, &MirSurfaceItem::surfaceStateChanged);
290 QUrl qmlComponentFilePath;
291 if (!m_qmlSurface->qmlFilePath().isEmpty()) {
292 qmlComponentFilePath = m_qmlSurface->qmlFilePath();
293 } else {
294 qmlComponentFilePath = QUrl("qrc:///Unity/Application/MirSurfaceItem.qml");
295 }
297 m_qmlContentComponent = new QQmlComponent(QQmlEngine::contextForObject(parent())->engine(), qmlComponentFilePath);
299 switch (m_qmlContentComponent->status()) {
300 case QQmlComponent::Ready:
301 createQmlContentItem();
302 break;
303 case QQmlComponent::Loading:
304 connect(m_qmlContentComponent, &QQmlComponent::statusChanged,
305 this, &MirSurfaceItem::onComponentStatusChanged);
306 break;
307 case QQmlComponent::Error:
308 printComponentErrors();
309 qFatal("MirSurfaceItem: failed to create content component.");
310 break;
311 default:
312 qFatal("MirSurfaceItem: Unhandled component status");
313 }
315 if (m_consumesInput) {
316 m_qmlSurface->setActiveFocus(hasActiveFocus());
317 }
318 }
320 Q_EMIT surfaceChanged(m_qmlSurface);
324void MirSurfaceItem::updateMirSurfaceActiveFocus(bool focused)
326 if (m_qmlSurface && m_consumesInput && m_qmlSurface->live()) {
327 m_qmlSurface->setActiveFocus(focused);
328 }
331void MirSurfaceItem::updateMirSurfaceVisibility()
333 if (!m_qmlSurface) return;
335 m_qmlSurface->setViewVisibility((qintptr)this, isVisible());
338void MirSurfaceItem::setConsumesInput(bool value)
340 if (m_consumesInput != value) {
341 m_consumesInput = value;
342 Q_EMIT consumesInputChanged(value);
343 }
346int MirSurfaceItem::surfaceWidth() const
348 return m_surfaceWidth;
351void MirSurfaceItem::setSurfaceWidth(int value)
353 if (value != -1 && m_surfaceWidth != value) {
354 m_surfaceWidth = value;
355 Q_EMIT surfaceWidthChanged(m_surfaceWidth);
356 updateSurfaceSize();
357 }
360int MirSurfaceItem::surfaceHeight() const
362 return m_surfaceHeight;
365void MirSurfaceItem::setSurfaceHeight(int value)
367 if (value != -1 && m_surfaceHeight != value) {
368 m_surfaceHeight = value;
369 Q_EMIT surfaceHeightChanged(m_surfaceHeight);
370 updateSurfaceSize();
371 }
374void MirSurfaceItem::updateSurfaceSize()
376 if (m_qmlSurface && m_surfaceWidth > 0 && m_surfaceHeight > 0) {
377 m_qmlSurface->resize(m_surfaceWidth, m_surfaceHeight);
378 }
381void MirSurfaceItem::setFillMode(FillMode value)
383 if (value != m_fillMode) {
384 m_fillMode = value;
385 Q_EMIT fillModeChanged(m_fillMode);
386 }