on e5699ca help sign in
519 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 }
262bool MirSurface::activeFocus() const
264 return m_activeFocus;
267void MirSurface::setActiveFocus(bool value)
269 if (m_activeFocus == value)
270 return;
272 m_activeFocus = value;
274 Q_EMIT activeFocusChanged(value);
277int MirSurface::width() const
279 return m_width;
282int MirSurface::height() const
284 return m_height;
287void MirSurface::resize(int width, int height)
289 if (m_slowToResize) {
290 if (!m_delayedResizeTimer.isActive()) {
291 m_delayedResize.setWidth(width);
292 m_delayedResize.setHeight(height);
293 m_delayedResizeTimer.start();
294 } else {
295 m_pendingResize.setWidth(width);
296 m_pendingResize.setHeight(height);
297 }
298 } else {
299 doResize(width, height);
300 }
303void MirSurface::applyDelayedResize()
305 doResize(m_delayedResize.width(), m_delayedResize.height());
306 m_delayedResize.setWidth(-1);
307 m_delayedResize.setHeight(-1);
309 if (m_pendingResize.isValid()) {
310 QSize size = m_pendingResize;
311 m_pendingResize.setWidth(-1);
312 m_pendingResize.setHeight(-1);
313 resize(size.width(), size.height());
314 }
317void MirSurface::doResize(int width, int height)
319 bool changed = false;
321 if (width != m_width) {
322 m_width = width;
323 Q_EMIT widthChanged();
324 changed = true;
325 }
327 if (m_height != height) {
328 m_height = height;
329 Q_EMIT heightChanged();
330 changed = true;
331 }
333 if (changed) {
334 Q_EMIT sizeChanged(QSize(width, height));
335 }
337 updateInputBoundsAfterResize();
340void MirSurface::updateInputBoundsAfterResize()
342 setInputBounds(QRect(0, 0, m_width, m_height));
345bool MirSurface::isSlowToResize() const
347 return m_slowToResize;
350void MirSurface::setSlowToResize(bool value)
352 if (m_slowToResize != value) {
353 DEBUG_MSG(value);
354 m_slowToResize = value;
355 Q_EMIT slowToResizeChanged();
356 if (!m_slowToResize && m_delayedResizeTimer.isActive()) {
357 m_delayedResizeTimer.stop();
358 applyDelayedResize();
359 }
360 }
363void MirSurface::setMinimumWidth(int value)
365 if (value != m_minimumWidth) {
366 m_minimumWidth = value;
367 Q_EMIT minimumWidthChanged(m_minimumWidth);
368 }
371void MirSurface::setMaximumWidth(int value)
373 if (value != m_maximumWidth) {
374 m_maximumWidth = value;
375 Q_EMIT maximumWidthChanged(m_maximumWidth);
376 }
379void MirSurface::setMinimumHeight(int value)
381 if (value != m_minimumHeight) {
382 m_minimumHeight = value;
383 Q_EMIT minimumHeightChanged(m_minimumHeight);
384 }
387void MirSurface::setMaximumHeight(int value)
389 if (value != m_maximumHeight) {
390 m_maximumHeight = value;
391 Q_EMIT maximumHeightChanged(m_maximumHeight);
392 }
395void MirSurface::setWidthIncrement(int value)
397 if (value != m_widthIncrement) {
398 m_widthIncrement = value;
399 Q_EMIT widthIncrementChanged(m_widthIncrement);
400 }
403void MirSurface::setHeightIncrement(int value)
405 if (value != m_heightIncrement) {
406 m_heightIncrement = value;
407 Q_EMIT heightIncrementChanged(m_heightIncrement);
408 }
411void MirSurface::raise()
413 Q_EMIT raiseRequested();
416void MirSurface::close()
418 DEBUG_MSG("");
419 if (!m_zombieTimer.isActive()) {
420 m_zombieTimer.start();
421 Q_EMIT closeRequested();
422 }
425void MirSurface::requestFocus()
427 DEBUG_MSG("");
428 Q_EMIT focusRequested();
431void MirSurface::setFocused(bool value)
433 DEBUG_MSG(value);
435 auto controller = MirFocusController::instance();
436 // controller instance might have been already destroyed by QQmlEngine destructor
437 if (!controller) {
438 return;
439 }
441 if (value) {
442 controller->setFocusedSurface(this);
443 } else if (controller->focusedSurface() == this) {
444 controller->setFocusedSurface(nullptr);
445 }
448bool MirSurface::focused() const
450 auto controller = MirFocusController::instance();
452 // controller instance might have been already destroyed by QQmlEngine destructor
453 return controller ? controller->focusedSurface() == this : false;
456QRect MirSurface::inputBounds() const
458 return m_inputBounds;
461void MirSurface::setInputBounds(const QRect &boundsRect)
463 if (boundsRect != m_inputBounds) {
464 m_inputBounds = boundsRect;
465 Q_EMIT inputBoundsChanged(m_inputBounds);
466 }
468#if MIRSURFACE_DEBUG
469#undef DEBUG_MSG
470#define DEBUG_MSG(params) qDebug().nospace() << "MirFocusController::" << __func__ << " " << params
471#endif
473void MirFocusController::setFocusedSurface(MirSurfaceInterface *surface)
475 if (m_focusedSurface == surface) {
476 return;
477 }
478 DEBUG_MSG("MirSurface[" << (void*)surface << "," << (surface?surface->name():"") << "]");
480 m_previouslyFocusedSurface = m_focusedSurface;
481 m_focusedSurface = surface;
483 if (m_previouslyFocusedSurface != m_focusedSurface) {
484 Q_EMIT focusedSurfaceChanged();
485 }
487 if (m_previouslyFocusedSurface) {
488 Q_EMIT m_previouslyFocusedSurface->focusedChanged(false);
489 }
491 if (m_focusedSurface) {
492 Q_EMIT m_focusedSurface->focusedChanged(true);
493 m_focusedSurface->raise();
494 }
497MirFocusController* MirFocusController::instance()
499 return m_instance;
502MirFocusController::MirFocusController()
504 DEBUG_MSG("");
505 Q_ASSERT(m_instance == nullptr);
506 m_instance = this;
509MirFocusController::~MirFocusController()
511 Q_ASSERT(m_instance == this);
512 m_instance = nullptr;
515void MirFocusController::clear()
517 m_focusedSurface = m_previouslyFocusedSurface = nullptr;
518 Q_EMIT focusedSurfaceChanged();