on 2ce36d2 help sign in
513 lines 12 kB history raw
1/*
2 * Copyright (C) 2015-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 "MirSurface.h"
19#include <QDebug>
20#include <QQmlEngine>
22#define MIRSURFACE_DEBUG 0
24#if MIRSURFACE_DEBUG
25#define DEBUG_MSG(params) qDebug().nospace() << "MirSurface[" << (void*)this << "," << m_name << "]::" << __func__ << " " << params
27const char *stateToStr(Mir::State state)
29 switch(state) {
30 case Mir::UnknownState:
31 return "unknown";
32 case Mir::RestoredState:
33 return "restored";
34 case Mir::MinimizedState:
35 return "minimized";
36 case Mir::MaximizedState:
37 return "maximized";
38 case Mir::VertMaximizedState:
39 return "vert-maximized";
40 case Mir::FullscreenState:
41 return "fullscreen";
42 case Mir::HorizMaximizedState:
43 return "horiz-maximized";
44 case Mir::HiddenState:
45 return "hidden";
46 default:
47 return "???";
48 };
51#else
52#define DEBUG_MSG(params) ((void)0)
53#endif
55using namespace unity::shell::application;
57MirFocusController *MirFocusController::m_instance = nullptr;
59MirSurface::MirSurface(const QString& name,
60 Mir::Type type,
61 Mir::State state,
62 const QUrl& screenshot,
63 const QUrl &qmlFilePath)
64 : unity::shell::application::MirSurfaceInterface(nullptr)
65 , m_name(name)
66 , m_type(type)
67 , m_state(state)
68 , m_orientationAngle(Mir::Angle0)
69 , m_screenshotUrl(screenshot)
70 , m_qmlFilePath(qmlFilePath)
71 , m_live(true)
72 , m_visible(true)
73 , m_activeFocus(false)
74 , m_width(-1)
75 , m_height(-1)
76 , m_slowToResize(false)
77 , m_shellChrome(Mir::NormalChrome)
79 DEBUG_MSG("");
81 QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
83 m_delayedResizeTimer.setInterval(600);
84 m_delayedResizeTimer.setSingleShot(true);
85 connect(&m_delayedResizeTimer, &QTimer::timeout, this, &MirSurface::applyDelayedResize);
87 m_zombieTimer.setInterval(100);
88 m_zombieTimer.setSingleShot(true);
89 connect(&m_zombieTimer, &QTimer::timeout, this, [this](){ this->setLive(false); });
92MirSurface::~MirSurface()
94 DEBUG_MSG("");
96 // controller instance might have been already destroyed by QQmlEngine destructor
97 auto controller = MirFocusController::instance();
98 if (controller && controller->focusedSurface() == this) {
99 controller->clear();
100 }
103QString MirSurface::name() const
105 return m_name;
108Mir::Type MirSurface::type() const
110 return m_type;
113Mir::State MirSurface::state() const
115 return m_state;
118void MirSurface::setState(Mir::State state)
120 if (state == m_state)
121 return;
123 DEBUG_MSG(stateToStr(state));
124 m_state = state;
125 Q_EMIT stateChanged(state);
128bool MirSurface::live() const
130 return m_live;
133bool MirSurface::visible() const
135 return m_visible;
138void MirSurface::setLive(bool live)
140 if (live == m_live)
141 return;
143 DEBUG_MSG(live);
144 m_live = live;
145 Q_EMIT liveChanged(live);
147 if (!m_live && m_views.count() == 0) {
148 deleteLater();
149 }
152QUrl MirSurface::qmlFilePath() const
154 return m_qmlFilePath;
157QUrl MirSurface::screenshotUrl() const
159 return m_screenshotUrl;
162void MirSurface::setScreenshotUrl(QUrl screenshotUrl)
164 if (screenshotUrl == m_screenshotUrl)
165 return;
167 m_screenshotUrl = screenshotUrl;
168 Q_EMIT screenshotUrlChanged(screenshotUrl);
171Mir::OrientationAngle MirSurface::orientationAngle() const
173 return m_orientationAngle;
176void MirSurface::setOrientationAngle(Mir::OrientationAngle angle)
178 if (angle == m_orientationAngle)
179 return;
181 m_orientationAngle = angle;
182 Q_EMIT orientationAngleChanged(angle);
185void MirSurface::setKeymap(const QString &value)
187 if (value != m_keymap) {
188 DEBUG_MSG(value);
189 m_keymap = value;
190 Q_EMIT keymapChanged(m_keymap);
191 }
194QString MirSurface::keymap() const
196 return m_keymap;
199Mir::ShellChrome MirSurface::shellChrome() const
201 return m_shellChrome;
204void MirSurface::setShellChrome(Mir::ShellChrome shellChrome)
206 if (shellChrome == m_shellChrome)
207 return;
209 DEBUG_MSG(shellChrome);
210 m_shellChrome = shellChrome;
211 Q_EMIT shellChromeChanged(shellChrome);
214void MirSurface::registerView(qintptr viewId)
216 m_views.insert(viewId, MirSurface::View{false});
217 DEBUG_MSG(viewId << " after=" << m_views.count());
220void MirSurface::unregisterView(qintptr viewId)
222 m_views.remove(viewId);
223 DEBUG_MSG(viewId << " after=" << m_views.count() << " live=" << m_live);
224 if (!m_live && m_views.count() == 0) {
225 deleteLater();
226 }
227 updateVisibility();
230void MirSurface::setViewVisibility(qintptr viewId, bool visible)
232 if (!m_views.contains(viewId)) return;
234 m_views[viewId].visible = visible;
235 updateVisibility();
238void MirSurface::updateVisibility()
240 bool newVisible = false;
241 QHashIterator<qintptr, View> i(m_views);
242 while (i.hasNext()) {
243 i.next();
244 newVisible |= i.value().visible;
245 }
247 if (newVisible != visible()) {
248// qDebug().nospace() << "MirSurface[" << name() << "]::updateVisibility(" << newVisible << ")";
250 m_visible = newVisible;
251 Q_EMIT visibleChanged(m_visible);
252 }
255bool MirSurface::activeFocus() const
257 return m_activeFocus;
260void MirSurface::setActiveFocus(bool value)
262 if (m_activeFocus == value)
263 return;
265 m_activeFocus = value;
267 Q_EMIT activeFocusChanged(value);
270int MirSurface::width() const
272 return m_width;
275int MirSurface::height() const
277 return m_height;
280void MirSurface::resize(int width, int height)
282 if (m_slowToResize) {
283 if (!m_delayedResizeTimer.isActive()) {
284 m_delayedResize.setWidth(width);
285 m_delayedResize.setHeight(height);
286 m_delayedResizeTimer.start();
287 } else {
288 m_pendingResize.setWidth(width);
289 m_pendingResize.setHeight(height);
290 }
291 } else {
292 doResize(width, height);
293 }
296void MirSurface::applyDelayedResize()
298 doResize(m_delayedResize.width(), m_delayedResize.height());
299 m_delayedResize.setWidth(-1);
300 m_delayedResize.setHeight(-1);
302 if (m_pendingResize.isValid()) {
303 QSize size = m_pendingResize;
304 m_pendingResize.setWidth(-1);
305 m_pendingResize.setHeight(-1);
306 resize(size.width(), size.height());
307 }
310void MirSurface::doResize(int width, int height)
312 bool changed = false;
314 if (width != m_width) {
315 m_width = width;
316 Q_EMIT widthChanged();
317 changed = true;
318 }
320 if (m_height != height) {
321 m_height = height;
322 Q_EMIT heightChanged();
323 changed = true;
324 }
326 if (changed) {
327 Q_EMIT sizeChanged(QSize(width, height));
328 }
331bool MirSurface::isSlowToResize() const
333 return m_slowToResize;
336void MirSurface::setSlowToResize(bool value)
338 if (m_slowToResize != value) {
339 DEBUG_MSG(value);
340 m_slowToResize = value;
341 Q_EMIT slowToResizeChanged();
342 if (!m_slowToResize && m_delayedResizeTimer.isActive()) {
343 m_delayedResizeTimer.stop();
344 applyDelayedResize();
345 }
346 }
349void MirSurface::setMinimumWidth(int value)
351 if (value != m_minimumWidth) {
352 m_minimumWidth = value;
353 Q_EMIT minimumWidthChanged(m_minimumWidth);
354 }
357void MirSurface::setMaximumWidth(int value)
359 if (value != m_maximumWidth) {
360 m_maximumWidth = value;
361 Q_EMIT maximumWidthChanged(m_maximumWidth);
362 }
365void MirSurface::setMinimumHeight(int value)
367 if (value != m_minimumHeight) {
368 m_minimumHeight = value;
369 Q_EMIT minimumHeightChanged(m_minimumHeight);
370 }
373void MirSurface::setMaximumHeight(int value)
375 if (value != m_maximumHeight) {
376 m_maximumHeight = value;
377 Q_EMIT maximumHeightChanged(m_maximumHeight);
378 }
381void MirSurface::setWidthIncrement(int value)
383 if (value != m_widthIncrement) {
384 m_widthIncrement = value;
385 Q_EMIT widthIncrementChanged(m_widthIncrement);
386 }
389void MirSurface::setHeightIncrement(int value)
391 if (value != m_heightIncrement) {
392 m_heightIncrement = value;
393 Q_EMIT heightIncrementChanged(m_heightIncrement);
394 }
397void MirSurface::raise()
399 Q_EMIT raiseRequested();
402void MirSurface::close()
404 DEBUG_MSG("");
405 if (!m_zombieTimer.isActive()) {
406 m_zombieTimer.start();
407 Q_EMIT closeRequested();
408 }
411void MirSurface::createPromptSurface()
413 QStringList screenshotIds = {"gallery", "map", "facebook", "camera", "browser", "music", "twitter"};
414 int i = rand() % screenshotIds.count();
416 QUrl screenshotUrl = QString("qrc:///Unity/Application/screenshots/%1@12.png")
417 .arg(screenshotIds[i]);
419 auto surface = new MirSurface(QString("prompt foo"),
420 Mir::NormalType,
421 Mir::RestoredState,
422 screenshotUrl);
424 m_promptSurfaceList.appendSurface(surface);
427MirSurfaceListInterface* MirSurface::promptSurfaceList()
429 return &m_promptSurfaceList;
432void MirSurface::requestFocus()
434 DEBUG_MSG("");
435 Q_EMIT focusRequested();
438void MirSurface::setFocused(bool value)
440 DEBUG_MSG(value);
442 auto controller = MirFocusController::instance();
443 // controller instance might have been already destroyed by QQmlEngine destructor
444 if (!controller) {
445 return;
446 }
448 if (value) {
449 controller->setFocusedSurface(this);
450 } else if (controller->focusedSurface() == this) {
451 controller->setFocusedSurface(nullptr);
452 }
455bool MirSurface::focused() const
457 auto controller = MirFocusController::instance();
459 // controller instance might have been already destroyed by QQmlEngine destructor
460 return controller ? controller->focusedSurface() == this : false;
463#if MIRSURFACE_DEBUG
464#undef DEBUG_MSG
465#define DEBUG_MSG(params) qDebug().nospace() << "MirFocusController::" << __func__ << " " << params
466#endif
468void MirFocusController::setFocusedSurface(MirSurfaceInterface *surface)
470 if (m_focusedSurface == surface) {
471 return;
472 }
473 DEBUG_MSG("MirSurface[" << (void*)surface << "," << (surface?surface->name():"") << "]");
475 m_previouslyFocusedSurface = m_focusedSurface;
476 m_focusedSurface = surface;
478 if (m_previouslyFocusedSurface != m_focusedSurface) {
479 Q_EMIT focusedSurfaceChanged();
480 }
482 if (m_previouslyFocusedSurface) {
483 Q_EMIT m_previouslyFocusedSurface->focusedChanged(false);
484 }
486 if (m_focusedSurface) {
487 Q_EMIT m_focusedSurface->focusedChanged(true);
488 }
491MirFocusController* MirFocusController::instance()
493 return m_instance;
496MirFocusController::MirFocusController()
498 DEBUG_MSG("");
499 Q_ASSERT(m_instance == nullptr);
500 m_instance = this;
503MirFocusController::~MirFocusController()
505 Q_ASSERT(m_instance == this);
506 m_instance = nullptr;
509void MirFocusController::clear()
511 m_focusedSurface = m_previouslyFocusedSurface = nullptr;
512 Q_EMIT focusedSurfaceChanged();