on 19581a6 help sign in
unity8/tests/mocks/Unity/Application/MirSurfaceItem.cpp
373 lines 10 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_surfaceWidth(0)
47 , m_surfaceHeight(0)
48 , m_touchPressCount(0)
49 , m_touchReleaseCount(0)
50 , m_mousePressCount(0)
51 , m_mouseReleaseCount(0)
53 DEBUG_MSG((void*)(this) << name());
54 setAcceptedMouseButtons(Qt::LeftButton | Qt::MiddleButton | Qt::RightButton |
55 Qt::ExtraButton1 | Qt::ExtraButton2 | Qt::ExtraButton3 | Qt::ExtraButton4 |
56 Qt::ExtraButton5 | Qt::ExtraButton6 | Qt::ExtraButton7 | Qt::ExtraButton8 |
57 Qt::ExtraButton9 | Qt::ExtraButton10 | Qt::ExtraButton11 |
58 Qt::ExtraButton12 | Qt::ExtraButton13);
60 connect(this, &QQuickItem::activeFocusChanged, this, &MirSurfaceItem::updateMirSurfaceActiveFocus);
61 connect(this, &QQuickItem::visibleChanged, this, &MirSurfaceItem::updateMirSurfaceVisibility);
63 connect(this, &MirSurfaceItem::consumesInputChanged, this, [this]() {
64 updateMirSurfaceActiveFocus(hasActiveFocus());
65 });
67 // We're just clipping contents in the mock. The real QtMir would copy only relevant buffer instead
68 setClip(true);
71MirSurfaceItem::~MirSurfaceItem()
73 DEBUG_MSG((void*)(this) << name());
74 setSurface(nullptr);
77void MirSurfaceItem::printComponentErrors()
79 QList<QQmlError> errors = m_qmlContentComponent->errors();
80 for (int i = 0; i < errors.count(); ++i) {
81 qDebug() << errors[i];
82 }
85Mir::Type MirSurfaceItem::type() const
87 if (m_qmlSurface) {
88 return m_qmlSurface->type();
89 } else {
90 return Mir::UnknownType;
91 }
94Mir::State MirSurfaceItem::surfaceState() const
96 if (m_qmlSurface) {
97 return m_qmlSurface->state();
98 } else {
99 return Mir::UnknownState;
100 }
103QString MirSurfaceItem::name() const
105 if (m_qmlSurface) {
106 return m_qmlSurface->name();
107 } else {
108 return QString();
109 }
112bool MirSurfaceItem::live() const
114 if (m_qmlSurface) {
115 return m_qmlSurface->live();
116 } else {
117 return false;
118 }
121Mir::ShellChrome MirSurfaceItem::shellChrome() const
123 if (m_qmlSurface) {
124 return m_qmlSurface->shellChrome();
125 } else {
126 return Mir::NormalChrome;
127 }
130Mir::OrientationAngle MirSurfaceItem::orientationAngle() const
132 if (m_qmlSurface) {
133 return m_qmlSurface->orientationAngle();
134 } else {
135 return Mir::Angle0;
136 }
139void MirSurfaceItem::setOrientationAngle(Mir::OrientationAngle angle)
141 if (!m_qmlSurface)
142 return;
144 if (m_qmlSurface->orientationAngle() == angle)
145 return;
147 m_qmlSurface->setOrientationAngle(angle);
149 QQmlProperty orientationProp(m_qmlItem, "orientationAngle");
150 orientationProp.write(QVariant::fromValue(m_qmlSurface->orientationAngle()));
153void MirSurfaceItem::updateScreenshot(QUrl screenshotUrl)
155 if (m_qmlItem) {
156 QQmlProperty screenshotSource(m_qmlItem, "screenshotSource");
157 screenshotSource.write(QVariant::fromValue(screenshotUrl));
158 }
161void MirSurfaceItem::onComponentStatusChanged(QQmlComponent::Status status)
163 if (status == QQmlComponent::Ready) {
164 createQmlContentItem();
165 }
168void MirSurfaceItem::createQmlContentItem()
170 DEBUG_MSG("");
172 m_qmlItem = qobject_cast<QQuickItem*>(m_qmlContentComponent->create());
173 m_qmlItem->setParentItem(this);
175 m_qmlItem->setWidth(m_surfaceWidth);
176 m_qmlItem->setHeight(m_surfaceHeight);
178 setImplicitWidth(m_qmlItem->implicitWidth());
179 setImplicitHeight(m_qmlItem->implicitHeight());
181 {
182 QQmlProperty screenshotSource(m_qmlItem, "screenshotSource");
183 screenshotSource.write(QVariant::fromValue(m_qmlSurface->screenshotUrl()));
184 }
187void MirSurfaceItem::touchEvent(QTouchEvent * event)
189 if (event->type() == QEvent::TouchBegin) {
190 m_touchTrail.clear();
191 }
193 if (event->touchPointStates() & Qt::TouchPointPressed) {
194 ++m_touchPressCount;
195 Q_EMIT touchPressCountChanged(m_touchPressCount);
196 } else if (event->touchPointStates() & Qt::TouchPointReleased) {
197 ++m_touchReleaseCount;
198 Q_EMIT touchReleaseCountChanged(m_touchReleaseCount);
199 }
201 Q_FOREACH(QTouchEvent::TouchPoint touchPoint, event->touchPoints()) {
202 QString id(touchPoint.id());
203 QVariantList list = m_touchTrail[id].toList();
204 list.append(QVariant::fromValue(touchPoint.pos()));
205 if (list.count() > 100) list.pop_front();
206 m_touchTrail[id] = list;
207 }
209 if (m_qmlItem) {
210 QQmlProperty touchTrail(m_qmlItem, "touchTrail");
211 touchTrail.write(m_touchTrail);
212 }
215void MirSurfaceItem::mousePressEvent(QMouseEvent * event)
217 m_mousePressCount++;
218 Q_EMIT mousePressCountChanged(m_mousePressCount);
219 event->accept();
222void MirSurfaceItem::mouseMoveEvent(QMouseEvent * event)
224 event->accept();
227void MirSurfaceItem::mouseReleaseEvent(QMouseEvent * event)
229 m_mouseReleaseCount++;
230 Q_EMIT mouseReleaseCountChanged(m_mouseReleaseCount);
231 event->accept();
234void MirSurfaceItem::setSurface(MirSurfaceInterface* surface)
236 DEBUG_MSG("this=" << (void*)(this) << " name=" << name() << " surface=" << surface);
238 if (m_qmlSurface == surface) {
239 return;
240 }
242 if (m_qmlSurface) {
243 delete m_qmlItem;
244 m_qmlItem = nullptr;
246 delete m_qmlContentComponent;
247 m_qmlContentComponent = nullptr;
249 if (hasActiveFocus() && m_consumesInput && m_qmlSurface->live()) {
250 m_qmlSurface->setActiveFocus(false);
251 }
253 disconnect(m_qmlSurface, nullptr, this, nullptr);
254 m_qmlSurface->unregisterView((qintptr)this);
255 }
257 m_qmlSurface = static_cast<MirSurface*>(surface);
259 if (m_qmlSurface) {
260 m_qmlSurface->registerView((qintptr)this);
262 updateSurfaceSize();
263 updateMirSurfaceVisibility();
265 connect(m_qmlSurface, &MirSurface::orientationAngleChanged, this, &MirSurfaceItem::orientationAngleChanged);
266 connect(m_qmlSurface, &MirSurface::screenshotUrlChanged, this, &MirSurfaceItem::updateScreenshot);
267 connect(m_qmlSurface, &MirSurface::liveChanged, this, &MirSurfaceItem::liveChanged);
268 connect(m_qmlSurface, &MirSurface::stateChanged, this, &MirSurfaceItem::surfaceStateChanged);
270 QUrl qmlComponentFilePath;
271 if (!m_qmlSurface->qmlFilePath().isEmpty()) {
272 qmlComponentFilePath = m_qmlSurface->qmlFilePath();
273 } else {
274 qmlComponentFilePath = QUrl("qrc:///Unity/Application/MirSurfaceItem.qml");
275 }
277 m_qmlContentComponent = new QQmlComponent(QQmlEngine::contextForObject(parent())->engine(), qmlComponentFilePath);
279 switch (m_qmlContentComponent->status()) {
280 case QQmlComponent::Ready:
281 createQmlContentItem();
282 break;
283 case QQmlComponent::Loading:
284 connect(m_qmlContentComponent, &QQmlComponent::statusChanged,
285 this, &MirSurfaceItem::onComponentStatusChanged);
286 break;
287 case QQmlComponent::Error:
288 printComponentErrors();
289 qFatal("MirSurfaceItem: failed to create content component.");
290 break;
291 default:
292 qFatal("MirSurfaceItem: Unhandled component status");
293 }
295 if (m_consumesInput) {
296 m_qmlSurface->setActiveFocus(hasActiveFocus());
297 }
298 }
300 Q_EMIT surfaceChanged(m_qmlSurface);
304void MirSurfaceItem::updateMirSurfaceActiveFocus(bool focused)
306 if (m_qmlSurface && m_consumesInput && m_qmlSurface->live()) {
307 m_qmlSurface->setActiveFocus(focused);
308 }
311void MirSurfaceItem::updateMirSurfaceVisibility()
313 if (!m_qmlSurface) return;
315 m_qmlSurface->setViewVisibility((qintptr)this, isVisible());
318void MirSurfaceItem::setConsumesInput(bool value)
320 if (m_consumesInput != value) {
321 m_consumesInput = value;
322 Q_EMIT consumesInputChanged(value);
323 }
326int MirSurfaceItem::surfaceWidth() const
328 return m_surfaceWidth;
331void MirSurfaceItem::setSurfaceWidth(int value)
333 qDebug() << "setSurfaceWidth called" << value;
334 if (value != -1 && m_surfaceWidth != value) {
335 m_surfaceWidth = value;
336 Q_EMIT surfaceWidthChanged(m_surfaceWidth);
337 updateSurfaceSize();
338 }
341int MirSurfaceItem::surfaceHeight() const
343 return m_surfaceHeight;
346void MirSurfaceItem::setSurfaceHeight(int value)
348 if (value != -1 && m_surfaceHeight != value) {
349 m_surfaceHeight = value;
350 Q_EMIT surfaceHeightChanged(m_surfaceHeight);
351 updateSurfaceSize();
352 }
355void MirSurfaceItem::updateSurfaceSize()
357 if (m_qmlSurface && m_surfaceWidth > 0 && m_surfaceHeight > 0) {
358 m_qmlSurface->resize(m_surfaceWidth, m_surfaceHeight);
359 if (m_qmlItem) {
360 m_qmlItem->setWidth(m_surfaceWidth);
361 m_qmlItem->setHeight(m_surfaceHeight);
362 }
363 setImplicitSize(m_surfaceWidth, m_surfaceHeight);
364 }
367void MirSurfaceItem::setFillMode(FillMode value)
369 if (value != m_fillMode) {
370 m_fillMode = value;
371 Q_EMIT fillModeChanged(m_fillMode);
372 }