on 660cc95 help sign in
514 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); });
91 updateInputBoundsAfterResize();
94MirSurface::~MirSurface()
96 DEBUG_MSG("");
98 // controller instance might have been already destroyed by QQmlEngine destructor
99 auto controller = MirFocusController::instance();
100 if (controller && controller->focusedSurface() == this) {
101 controller->clear();
102 }
105QString MirSurface::name() const
107 return m_name;
110Mir::Type MirSurface::type() const
112 return m_type;
115Mir::State MirSurface::state() const
117 return m_state;
120void MirSurface::setState(Mir::State state)
122 if (state == m_state)
123 return;
125 DEBUG_MSG(stateToStr(state));
126 m_state = state;
127 Q_EMIT stateChanged(state);
130bool MirSurface::live() const
132 return m_live;
135bool MirSurface::visible() const
137 return m_visible;
140void MirSurface::setLive(bool live)
142 if (live == m_live)
143 return;
145 DEBUG_MSG(live);
146 m_live = live;
147 Q_EMIT liveChanged(live);
149 if (!m_live && m_views.count() == 0) {
150 deleteLater();
151 }
154QUrl MirSurface::qmlFilePath() const
156 return m_qmlFilePath;
159QUrl MirSurface::screenshotUrl() const
161 return m_screenshotUrl;
164void MirSurface::setScreenshotUrl(QUrl screenshotUrl)
166 if (screenshotUrl == m_screenshotUrl)
167 return;
169 m_screenshotUrl = screenshotUrl;
170 Q_EMIT screenshotUrlChanged(screenshotUrl);
173Mir::OrientationAngle MirSurface::orientationAngle() const
175 return m_orientationAngle;
178void MirSurface::setOrientationAngle(Mir::OrientationAngle angle)
180 if (angle == m_orientationAngle)
181 return;
183 m_orientationAngle = angle;
184 Q_EMIT orientationAngleChanged(angle);
187void MirSurface::setKeymap(const QString &value)
189 if (value != m_keymap) {
190 DEBUG_MSG(value);
191 m_keymap = value;
192 Q_EMIT keymapChanged(m_keymap);
193 }
196QString MirSurface::keymap() const
198 return m_keymap;
201Mir::ShellChrome MirSurface::shellChrome() const
203 return m_shellChrome;
206void MirSurface::setShellChrome(Mir::ShellChrome shellChrome)
208 if (shellChrome == m_shellChrome)
209 return;
211 DEBUG_MSG(shellChrome);
212 m_shellChrome = shellChrome;
213 Q_EMIT shellChromeChanged(shellChrome);
216void MirSurface::registerView(qintptr viewId)
218 m_views.insert(viewId, MirSurface::View{false});
219 DEBUG_MSG(viewId << " after=" << m_views.count());
222void MirSurface::unregisterView(qintptr viewId)
224 m_views.remove(viewId);
225 DEBUG_MSG(viewId << " after=" << m_views.count() << " live=" << m_live);
226 if (!m_live && m_views.count() == 0) {
227 deleteLater();
228 }
229 updateVisibility();
232void MirSurface::setViewVisibility(qintptr viewId, bool visible)
234 if (!m_views.contains(viewId)) return;
236 m_views[viewId].visible = visible;
237 updateVisibility();
240void MirSurface::updateVisibility()
242 bool newVisible = false;
243 QHashIterator<qintptr, View> i(m_views);
244 while (i.hasNext()) {
245 i.next();
246 newVisible |= i.value().visible;
247 }
249 if (newVisible != visible()) {
250// qDebug().nospace() << "MirSurface[" << name() << "]::updateVisibility(" << newVisible << ")";
252 m_visible = newVisible;
253 Q_EMIT visibleChanged(m_visible);
254 }
257bool MirSurface::activeFocus() const
259 return m_activeFocus;
262void MirSurface::setActiveFocus(bool value)
264 if (m_activeFocus == value)
265 return;
267 m_activeFocus = value;
269 Q_EMIT activeFocusChanged(value);
272int MirSurface::width() const
274 return m_width;
277int MirSurface::height() const
279 return m_height;
282void MirSurface::resize(int width, int height)
284 if (m_slowToResize) {
285 if (!m_delayedResizeTimer.isActive()) {
286 m_delayedResize.setWidth(width);
287 m_delayedResize.setHeight(height);
288 m_delayedResizeTimer.start();
289 } else {
290 m_pendingResize.setWidth(width);
291 m_pendingResize.setHeight(height);
292 }
293 } else {
294 doResize(width, height);
295 }
298void MirSurface::applyDelayedResize()
300 doResize(m_delayedResize.width(), m_delayedResize.height());
301 m_delayedResize.setWidth(-1);
302 m_delayedResize.setHeight(-1);
304 if (m_pendingResize.isValid()) {
305 QSize size = m_pendingResize;
306 m_pendingResize.setWidth(-1);
307 m_pendingResize.setHeight(-1);
308 resize(size.width(), size.height());
309 }
312void MirSurface::doResize(int width, int height)
314 bool changed = false;
316 if (width != m_width) {
317 m_width = width;
318 Q_EMIT widthChanged();
319 changed = true;
320 }
322 if (m_height != height) {
323 m_height = height;
324 Q_EMIT heightChanged();
325 changed = true;
326 }
328 if (changed) {
329 Q_EMIT sizeChanged(QSize(width, height));
330 }
332 updateInputBoundsAfterResize();
335void MirSurface::updateInputBoundsAfterResize()
337 setInputBounds(QRect(0, 0, m_width, m_height));
340bool MirSurface::isSlowToResize() const
342 return m_slowToResize;
345void MirSurface::setSlowToResize(bool value)
347 if (m_slowToResize != value) {
348 DEBUG_MSG(value);
349 m_slowToResize = value;
350 Q_EMIT slowToResizeChanged();
351 if (!m_slowToResize && m_delayedResizeTimer.isActive()) {
352 m_delayedResizeTimer.stop();
353 applyDelayedResize();
354 }
355 }
358void MirSurface::setMinimumWidth(int value)
360 if (value != m_minimumWidth) {
361 m_minimumWidth = value;
362 Q_EMIT minimumWidthChanged(m_minimumWidth);
363 }
366void MirSurface::setMaximumWidth(int value)
368 if (value != m_maximumWidth) {
369 m_maximumWidth = value;
370 Q_EMIT maximumWidthChanged(m_maximumWidth);
371 }
374void MirSurface::setMinimumHeight(int value)
376 if (value != m_minimumHeight) {
377 m_minimumHeight = value;
378 Q_EMIT minimumHeightChanged(m_minimumHeight);
379 }
382void MirSurface::setMaximumHeight(int value)
384 if (value != m_maximumHeight) {
385 m_maximumHeight = value;
386 Q_EMIT maximumHeightChanged(m_maximumHeight);
387 }
390void MirSurface::setWidthIncrement(int value)
392 if (value != m_widthIncrement) {
393 m_widthIncrement = value;
394 Q_EMIT widthIncrementChanged(m_widthIncrement);
395 }
398void MirSurface::setHeightIncrement(int value)
400 if (value != m_heightIncrement) {
401 m_heightIncrement = value;
402 Q_EMIT heightIncrementChanged(m_heightIncrement);
403 }
406void MirSurface::raise()
408 Q_EMIT raiseRequested();
411void MirSurface::close()
413 DEBUG_MSG("");
414 if (!m_zombieTimer.isActive()) {
415 m_zombieTimer.start();
416 Q_EMIT closeRequested();
417 }
420void MirSurface::requestFocus()
422 DEBUG_MSG("");
423 Q_EMIT focusRequested();
426void MirSurface::setFocused(bool value)
428 DEBUG_MSG(value);
430 auto controller = MirFocusController::instance();
431 // controller instance might have been already destroyed by QQmlEngine destructor
432 if (!controller) {
433 return;
434 }
436 if (value) {
437 controller->setFocusedSurface(this);
438 } else if (controller->focusedSurface() == this) {
439 controller->setFocusedSurface(nullptr);
440 }
443bool MirSurface::focused() const
445 auto controller = MirFocusController::instance();
447 // controller instance might have been already destroyed by QQmlEngine destructor
448 return controller ? controller->focusedSurface() == this : false;
451QRect MirSurface::inputBounds() const
453 return m_inputBounds;
456void MirSurface::setInputBounds(const QRect &boundsRect)
458 if (boundsRect != m_inputBounds) {
459 m_inputBounds = boundsRect;
460 Q_EMIT inputBoundsChanged(m_inputBounds);
461 }
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 m_focusedSurface->raise();
489 }
492MirFocusController* MirFocusController::instance()
494 return m_instance;
497MirFocusController::MirFocusController()
499 DEBUG_MSG("");
500 Q_ASSERT(m_instance == nullptr);
501 m_instance = this;
504MirFocusController::~MirFocusController()
506 Q_ASSERT(m_instance == this);
507 m_instance = nullptr;
510void MirFocusController::clear()
512 m_focusedSurface = m_previouslyFocusedSurface = nullptr;
513 Q_EMIT focusedSurfaceChanged();