on cfcde21 help sign in
520 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;
110QString MirSurface::persistentId() const
112 return m_name+"Id";
115Mir::Type MirSurface::type() const
117 return m_type;
120Mir::State MirSurface::state() const
122 return m_state;
125void MirSurface::setState(Mir::State state)
127 if (state == m_state)
128 return;
130 DEBUG_MSG(stateToStr(state));
131 m_state = state;
132 Q_EMIT stateChanged(state);
135bool MirSurface::live() const
137 return m_live;
140bool MirSurface::visible() const
142 return m_visible;
145void MirSurface::setLive(bool live)
147 if (live == m_live)
148 return;
150 DEBUG_MSG(live);
151 m_live = live;
152 Q_EMIT liveChanged(live);
154 if (!m_live && m_views.count() == 0) {
155 deleteLater();
156 }
159QUrl MirSurface::qmlFilePath() const
161 return m_qmlFilePath;
164QUrl MirSurface::screenshotUrl() const
166 return m_screenshotUrl;
169void MirSurface::setScreenshotUrl(QUrl screenshotUrl)
171 if (screenshotUrl == m_screenshotUrl)
172 return;
174 m_screenshotUrl = screenshotUrl;
175 Q_EMIT screenshotUrlChanged(screenshotUrl);
178Mir::OrientationAngle MirSurface::orientationAngle() const
180 return m_orientationAngle;
183void MirSurface::setOrientationAngle(Mir::OrientationAngle angle)
185 if (angle == m_orientationAngle)
186 return;
188 m_orientationAngle = angle;
189 Q_EMIT orientationAngleChanged(angle);
192void MirSurface::setKeymap(const QString &value)
194 if (value != m_keymap) {
195 DEBUG_MSG(value);
196 m_keymap = value;
197 Q_EMIT keymapChanged(m_keymap);
198 }
201QString MirSurface::keymap() const
203 return m_keymap;
206Mir::ShellChrome MirSurface::shellChrome() const
208 return m_shellChrome;
211void MirSurface::setShellChrome(Mir::ShellChrome shellChrome)
213 if (shellChrome == m_shellChrome)
214 return;
216 DEBUG_MSG(shellChrome);
217 m_shellChrome = shellChrome;
218 Q_EMIT shellChromeChanged(shellChrome);
221void MirSurface::registerView(qintptr viewId)
223 m_views.insert(viewId, MirSurface::View{false});
224 DEBUG_MSG(viewId << " after=" << m_views.count());
227void MirSurface::unregisterView(qintptr viewId)
229 m_views.remove(viewId);
230 DEBUG_MSG(viewId << " after=" << m_views.count() << " live=" << m_live);
231 if (!m_live && m_views.count() == 0) {
232 deleteLater();
233 }
234 updateVisibility();
237void MirSurface::setViewVisibility(qintptr viewId, bool visible)
239 if (!m_views.contains(viewId)) return;
241 m_views[viewId].visible = visible;
242 updateVisibility();
245void MirSurface::updateVisibility()
247 bool newVisible = false;
248 QHashIterator<qintptr, View> i(m_views);
249 while (i.hasNext()) {
250 i.next();
251 newVisible |= i.value().visible;
252 }
254 if (newVisible != visible()) {
255// qDebug().nospace() << "MirSurface[" << name() << "]::updateVisibility(" << newVisible << ")";
257 m_visible = newVisible;
258 Q_EMIT visibleChanged(m_visible);
259 updateInputBoundsAfterResize();
260 }
263bool MirSurface::activeFocus() const
265 return m_activeFocus;
268void MirSurface::setActiveFocus(bool value)
270 if (m_activeFocus == value)
271 return;
273 m_activeFocus = value;
275 Q_EMIT activeFocusChanged(value);
278int MirSurface::width() const
280 return m_width;
283int MirSurface::height() const
285 return m_height;
288void MirSurface::resize(int width, int height)
290 if (m_slowToResize) {
291 if (!m_delayedResizeTimer.isActive()) {
292 m_delayedResize.setWidth(width);
293 m_delayedResize.setHeight(height);
294 m_delayedResizeTimer.start();
295 } else {
296 m_pendingResize.setWidth(width);
297 m_pendingResize.setHeight(height);
298 }
299 } else {
300 doResize(width, height);
301 }
304void MirSurface::applyDelayedResize()
306 doResize(m_delayedResize.width(), m_delayedResize.height());
307 m_delayedResize.setWidth(-1);
308 m_delayedResize.setHeight(-1);
310 if (m_pendingResize.isValid()) {
311 QSize size = m_pendingResize;
312 m_pendingResize.setWidth(-1);
313 m_pendingResize.setHeight(-1);
314 resize(size.width(), size.height());
315 }
318void MirSurface::doResize(int width, int height)
320 bool changed = false;
322 if (width != m_width) {
323 m_width = width;
324 Q_EMIT widthChanged();
325 changed = true;
326 }
328 if (m_height != height) {
329 m_height = height;
330 Q_EMIT heightChanged();
331 changed = true;
332 }
334 if (changed) {
335 Q_EMIT sizeChanged(QSize(width, height));
336 }
338 updateInputBoundsAfterResize();
341void MirSurface::updateInputBoundsAfterResize()
343 setInputBounds(QRect(0, 0, m_width, m_height));
346bool MirSurface::isSlowToResize() const
348 return m_slowToResize;
351void MirSurface::setSlowToResize(bool value)
353 if (m_slowToResize != value) {
354 DEBUG_MSG(value);
355 m_slowToResize = value;
356 Q_EMIT slowToResizeChanged();
357 if (!m_slowToResize && m_delayedResizeTimer.isActive()) {
358 m_delayedResizeTimer.stop();
359 applyDelayedResize();
360 }
361 }
364void MirSurface::setMinimumWidth(int value)
366 if (value != m_minimumWidth) {
367 m_minimumWidth = value;
368 Q_EMIT minimumWidthChanged(m_minimumWidth);
369 }
372void MirSurface::setMaximumWidth(int value)
374 if (value != m_maximumWidth) {
375 m_maximumWidth = value;
376 Q_EMIT maximumWidthChanged(m_maximumWidth);
377 }
380void MirSurface::setMinimumHeight(int value)
382 if (value != m_minimumHeight) {
383 m_minimumHeight = value;
384 Q_EMIT minimumHeightChanged(m_minimumHeight);
385 }
388void MirSurface::setMaximumHeight(int value)
390 if (value != m_maximumHeight) {
391 m_maximumHeight = value;
392 Q_EMIT maximumHeightChanged(m_maximumHeight);
393 }
396void MirSurface::setWidthIncrement(int value)
398 if (value != m_widthIncrement) {
399 m_widthIncrement = value;
400 Q_EMIT widthIncrementChanged(m_widthIncrement);
401 }
404void MirSurface::setHeightIncrement(int value)
406 if (value != m_heightIncrement) {
407 m_heightIncrement = value;
408 Q_EMIT heightIncrementChanged(m_heightIncrement);
409 }
412void MirSurface::raise()
414 Q_EMIT raiseRequested();
417void MirSurface::close()
419 DEBUG_MSG("");
420 if (!m_zombieTimer.isActive()) {
421 m_zombieTimer.start();
422 Q_EMIT closeRequested();
423 }
426void MirSurface::requestFocus()
428 DEBUG_MSG("");
429 Q_EMIT focusRequested();
432void MirSurface::setFocused(bool value)
434 DEBUG_MSG(value);
436 auto controller = MirFocusController::instance();
437 // controller instance might have been already destroyed by QQmlEngine destructor
438 if (!controller) {
439 return;
440 }
442 if (value) {
443 controller->setFocusedSurface(this);
444 } else if (controller->focusedSurface() == this) {
445 controller->setFocusedSurface(nullptr);
446 }
449bool MirSurface::focused() const
451 auto controller = MirFocusController::instance();
453 // controller instance might have been already destroyed by QQmlEngine destructor
454 return controller ? controller->focusedSurface() == this : false;
457QRect MirSurface::inputBounds() const
459 return m_inputBounds;
462void MirSurface::setInputBounds(const QRect &boundsRect)
464 if (boundsRect != m_inputBounds) {
465 m_inputBounds = boundsRect;
466 Q_EMIT inputBoundsChanged(m_inputBounds);
467 }
469#if MIRSURFACE_DEBUG
470#undef DEBUG_MSG
471#define DEBUG_MSG(params) qDebug().nospace() << "MirFocusController::" << __func__ << " " << params
472#endif
474void MirFocusController::setFocusedSurface(MirSurfaceInterface *surface)
476 if (m_focusedSurface == surface) {
477 return;
478 }
479 DEBUG_MSG("MirSurface[" << (void*)surface << "," << (surface?surface->name():"") << "]");
481 m_previouslyFocusedSurface = m_focusedSurface;
482 m_focusedSurface = surface;
484 if (m_previouslyFocusedSurface != m_focusedSurface) {
485 Q_EMIT focusedSurfaceChanged();
486 }
488 if (m_previouslyFocusedSurface) {
489 Q_EMIT m_previouslyFocusedSurface->focusedChanged(false);
490 }
492 if (m_focusedSurface) {
493 Q_EMIT m_focusedSurface->focusedChanged(true);
494 m_focusedSurface->raise();
495 }
498MirFocusController* MirFocusController::instance()
500 return m_instance;
503MirFocusController::MirFocusController()
505 DEBUG_MSG("");
506 Q_ASSERT(m_instance == nullptr);
507 m_instance = this;
510MirFocusController::~MirFocusController()
512 Q_ASSERT(m_instance == this);
513 m_instance = nullptr;
516void MirFocusController::clear()
518 m_focusedSurface = m_previouslyFocusedSurface = nullptr;
519 Q_EMIT focusedSurfaceChanged();