on 7aff6f1 help sign in
unity8/tests/mocks/Unity/Application/MirSurfaceItem.cpp
362 lines 10.0 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_qmlItem(nullptr)
44 , m_consumesInput(false)
45 , m_surfaceWidth(0)
46 , m_surfaceHeight(0)
47 , m_touchPressCount(0)
48 , m_touchReleaseCount(0)
49 , m_mousePressCount(0)
50 , m_mouseReleaseCount(0)
52 DEBUG_MSG((void*)(this) << name());
53 setAcceptedMouseButtons(Qt::LeftButton | Qt::MiddleButton | Qt::RightButton |
54 Qt::ExtraButton1 | Qt::ExtraButton2 | Qt::ExtraButton3 | Qt::ExtraButton4 |
55 Qt::ExtraButton5 | Qt::ExtraButton6 | Qt::ExtraButton7 | Qt::ExtraButton8 |
56 Qt::ExtraButton9 | Qt::ExtraButton10 | Qt::ExtraButton11 |
57 Qt::ExtraButton12 | Qt::ExtraButton13);
59 connect(this, &QQuickItem::visibleChanged, this, &MirSurfaceItem::updateMirSurfaceVisibility);
61 // We're just clipping contents in the mock. The real QtMir would copy only relevant buffer instead
62 setClip(true);
65MirSurfaceItem::~MirSurfaceItem()
67 DEBUG_MSG((void*)(this) << name());
68 setSurface(nullptr);
71void MirSurfaceItem::printComponentErrors()
73 QList<QQmlError> errors = m_qmlContentComponent->errors();
74 for (int i = 0; i < errors.count(); ++i) {
75 qDebug() << errors[i];
76 }
79Mir::Type MirSurfaceItem::type() const
81 if (m_qmlSurface) {
82 return m_qmlSurface->type();
83 } else {
84 return Mir::UnknownType;
85 }
88Mir::State MirSurfaceItem::surfaceState() const
90 if (m_qmlSurface) {
91 return m_qmlSurface->state();
92 } else {
93 return Mir::UnknownState;
94 }
97QString MirSurfaceItem::name() const
99 if (m_qmlSurface) {
100 return m_qmlSurface->name();
101 } else {
102 return QString();
103 }
106bool MirSurfaceItem::live() const
108 if (m_qmlSurface) {
109 return m_qmlSurface->live();
110 } else {
111 return false;
112 }
115Mir::ShellChrome MirSurfaceItem::shellChrome() const
117 if (m_qmlSurface) {
118 return m_qmlSurface->shellChrome();
119 } else {
120 return Mir::NormalChrome;
121 }
124Mir::OrientationAngle MirSurfaceItem::orientationAngle() const
126 if (m_qmlSurface) {
127 return m_qmlSurface->orientationAngle();
128 } else {
129 return Mir::Angle0;
130 }
133void MirSurfaceItem::setOrientationAngle(Mir::OrientationAngle angle)
135 if (!m_qmlSurface)
136 return;
138 if (m_qmlSurface->orientationAngle() == angle)
139 return;
141 m_qmlSurface->setOrientationAngle(angle);
143 QQmlProperty orientationProp(m_qmlItem, "orientationAngle");
144 orientationProp.write(QVariant::fromValue(m_qmlSurface->orientationAngle()));
147void MirSurfaceItem::updateScreenshot(QUrl screenshotUrl)
149 if (m_qmlItem) {
150 QQmlProperty screenshotSource(m_qmlItem, "screenshotSource");
151 screenshotSource.write(QVariant::fromValue(screenshotUrl));
152 }
155void MirSurfaceItem::onComponentStatusChanged(QQmlComponent::Status status)
157 if (status == QQmlComponent::Ready) {
158 createQmlContentItem();
159 }
162void MirSurfaceItem::createQmlContentItem()
164 DEBUG_MSG("");
166 m_qmlItem = qobject_cast<QQuickItem*>(m_qmlContentComponent->create());
167 m_qmlItem->setParentItem(this);
169 m_qmlItem->setWidth(m_surfaceWidth);
170 m_qmlItem->setHeight(m_surfaceHeight);
172 setImplicitWidth(m_qmlItem->implicitWidth());
173 setImplicitHeight(m_qmlItem->implicitHeight());
175 {
176 QQmlProperty screenshotSource(m_qmlItem, "screenshotSource");
177 screenshotSource.write(QVariant::fromValue(m_qmlSurface->screenshotUrl()));
178 }
181void MirSurfaceItem::touchEvent(QTouchEvent * event)
183 if (event->type() == QEvent::TouchBegin) {
184 m_touchTrail.clear();
185 }
187 if (event->touchPointStates() & Qt::TouchPointPressed) {
188 ++m_touchPressCount;
189 Q_EMIT touchPressCountChanged(m_touchPressCount);
190 } else if (event->touchPointStates() & Qt::TouchPointReleased) {
191 ++m_touchReleaseCount;
192 Q_EMIT touchReleaseCountChanged(m_touchReleaseCount);
193 }
195 Q_FOREACH(QTouchEvent::TouchPoint touchPoint, event->touchPoints()) {
196 QString id(touchPoint.id());
197 QVariantList list = m_touchTrail[id].toList();
198 list.append(QVariant::fromValue(touchPoint.pos()));
199 if (list.count() > 100) list.pop_front();
200 m_touchTrail[id] = list;
201 }
203 if (m_qmlItem) {
204 QQmlProperty touchTrail(m_qmlItem, "touchTrail");
205 touchTrail.write(m_touchTrail);
206 }
209void MirSurfaceItem::mousePressEvent(QMouseEvent * event)
211 m_mousePressCount++;
212 Q_EMIT mousePressCountChanged(m_mousePressCount);
213 event->accept();
216void MirSurfaceItem::mouseMoveEvent(QMouseEvent * event)
218 event->accept();
221void MirSurfaceItem::mouseReleaseEvent(QMouseEvent * event)
223 m_mouseReleaseCount++;
224 Q_EMIT mouseReleaseCountChanged(m_mouseReleaseCount);
225 event->accept();
228void MirSurfaceItem::setSurface(MirSurfaceInterface* surface)
230 DEBUG_MSG("this=" << (void*)(this) << " name=" << name() << " surface=" << surface);
232 if (m_qmlSurface == surface) {
233 return;
234 }
236 if (m_qmlSurface) {
237 delete m_qmlItem;
238 m_qmlItem = nullptr;
240 delete m_qmlContentComponent;
241 m_qmlContentComponent = nullptr;
243 disconnect(m_qmlSurface, nullptr, this, nullptr);
244 m_qmlSurface->unregisterView((qintptr)this);
245 }
247 m_qmlSurface = static_cast<MirSurface*>(surface);
249 if (m_qmlSurface) {
250 m_qmlSurface->registerView((qintptr)this);
252 m_qmlSurface->setActiveFocus(hasActiveFocus());
254 updateSurfaceSize();
255 updateMirSurfaceVisibility();
257 connect(m_qmlSurface, &MirSurface::orientationAngleChanged, this, &MirSurfaceItem::orientationAngleChanged);
258 connect(m_qmlSurface, &MirSurface::screenshotUrlChanged, this, &MirSurfaceItem::updateScreenshot);
259 connect(m_qmlSurface, &MirSurface::liveChanged, this, &MirSurfaceItem::liveChanged);
260 connect(m_qmlSurface, &MirSurface::stateChanged, this, &MirSurfaceItem::surfaceStateChanged);
262 QUrl qmlComponentFilePath;
263 if (!m_qmlSurface->qmlFilePath().isEmpty()) {
264 qmlComponentFilePath = m_qmlSurface->qmlFilePath();
265 } else {
266 qmlComponentFilePath = QUrl("qrc:///Unity/Application/MirSurfaceItem.qml");
267 }
269 m_qmlContentComponent = new QQmlComponent(QQmlEngine::contextForObject(parent())->engine(), qmlComponentFilePath);
271 switch (m_qmlContentComponent->status()) {
272 case QQmlComponent::Ready:
273 createQmlContentItem();
274 break;
275 case QQmlComponent::Loading:
276 connect(m_qmlContentComponent, &QQmlComponent::statusChanged,
277 this, &MirSurfaceItem::onComponentStatusChanged);
278 break;
279 case QQmlComponent::Error:
280 printComponentErrors();
281 qFatal("MirSurfaceItem: failed to create content component.");
282 break;
283 default:
284 qFatal("MirSurfaceItem: Unhandled component status");
285 }
286 }
288 Q_EMIT surfaceChanged(m_qmlSurface);
291void MirSurfaceItem::itemChange(ItemChange change, const ItemChangeData & value)
293 if (change == QQuickItem::ItemActiveFocusHasChanged) {
294 if (m_qmlSurface) {
295 m_qmlSurface->setActiveFocus(value.boolValue);
296 }
297 }
300void MirSurfaceItem::updateMirSurfaceVisibility()
302 if (!m_qmlSurface) return;
304 m_qmlSurface->setViewVisibility((qintptr)this, isVisible());
307void MirSurfaceItem::setConsumesInput(bool value)
309 if (m_consumesInput != value) {
310 m_consumesInput = value;
311 Q_EMIT consumesInputChanged(value);
312 }
315int MirSurfaceItem::surfaceWidth() const
317 return m_surfaceWidth;
320void MirSurfaceItem::setSurfaceWidth(int value)
322 qDebug() << "setSurfaceWidth called" << value;
323 if (value != -1 && m_surfaceWidth != value) {
324 m_surfaceWidth = value;
325 Q_EMIT surfaceWidthChanged(m_surfaceWidth);
326 updateSurfaceSize();
327 }
330int MirSurfaceItem::surfaceHeight() const
332 return m_surfaceHeight;
335void MirSurfaceItem::setSurfaceHeight(int value)
337 if (value != -1 && m_surfaceHeight != value) {
338 m_surfaceHeight = value;
339 Q_EMIT surfaceHeightChanged(m_surfaceHeight);
340 updateSurfaceSize();
341 }
344void MirSurfaceItem::updateSurfaceSize()
346 if (m_qmlSurface && m_surfaceWidth > 0 && m_surfaceHeight > 0) {
347 m_qmlSurface->resize(m_surfaceWidth, m_surfaceHeight);
348 if (m_qmlItem) {
349 m_qmlItem->setWidth(m_surfaceWidth);
350 m_qmlItem->setHeight(m_surfaceHeight);
351 }
352 setImplicitSize(m_surfaceWidth, m_surfaceHeight);
353 }
356void MirSurfaceItem::setFillMode(FillMode value)
358 if (value != m_fillMode) {
359 m_fillMode = value;
360 Q_EMIT fillModeChanged(m_fillMode);
361 }