/*
* Copyright (C) 2015-2016 Canonical, Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#include "MirSurface.h"
#include
#include
// local
#include "SurfaceManager.h"
#define MIRSURFACE_DEBUG 0
#if MIRSURFACE_DEBUG
#define DEBUG_MSG(params) qDebug().nospace() << "MirSurface[" << (void*)this << "," << m_name << "]::" << __func__ << " " << params
#define XDEBUG_MSG(params) qDebug().nospace() << "MirSurface[" << (void*)this << "," << m_name << "]::" << params
const char *stateToStr(Mir::State state)
{
switch (state) {
case Mir::UnknownState:
return "unknown";
case Mir::RestoredState:
return "restored";
case Mir::MinimizedState:
return "minimized";
case Mir::MaximizedState:
return "maximized";
case Mir::VertMaximizedState:
return "vertMaximized";
case Mir::FullscreenState:
return "fullscreen";
case Mir::HorizMaximizedState:
return "horizMaximized";
case Mir::MaximizedLeftState:
return "maximizedLeft";
case Mir::MaximizedRightState:
return "maximizedRight";
case Mir::MaximizedTopLeftState:
return "maximizedTopLeft";
case Mir::MaximizedTopRightState:
return "maximizedTopRight";
case Mir::MaximizedBottomLeftState:
return "maximizedBottomLeft";
case Mir::MaximizedBottomRightState:
return "maximizedBottomRight";
case Mir::HiddenState:
return "hidden";
default:
return "???";
}
}
#else
#define DEBUG_MSG(params) ((void)0)
#define XDEBUG_MSG(params) ((void)0)
#endif
using namespace unity::shell::application;
MirSurface::MirSurface(const QString& name,
Mir::Type type,
Mir::State state,
MirSurface *parentSurface,
const QUrl& screenshot,
const QUrl &qmlFilePath)
: unity::shell::application::MirSurfaceInterface(nullptr)
, m_name(name)
, m_type(type)
, m_state(state)
, m_orientationAngle(Mir::Angle0)
, m_screenshotUrl(screenshot)
, m_qmlFilePath(qmlFilePath)
, m_live(true)
, m_focused(false)
, m_activeFocus(false)
, m_width(-1)
, m_height(-1)
, m_slowToResize(false)
, m_shellChrome(Mir::NormalChrome)
, m_parentSurface(parentSurface)
, m_childSurfaceList(new MirSurfaceListModel(this))
{
DEBUG_MSG("state=" << stateToStr(state));
QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
m_delayedResizeTimer.setInterval(600);
m_delayedResizeTimer.setSingleShot(true);
connect(&m_delayedResizeTimer, &QTimer::timeout, this, &MirSurface::applyDelayedResize);
m_zombieTimer.setInterval(100);
m_zombieTimer.setSingleShot(true);
connect(&m_zombieTimer, &QTimer::timeout, this, [this](){ this->setLive(false); });
updateInputBoundsAfterResize();
}
MirSurface::~MirSurface()
{
DEBUG_MSG("");
// Early warning, while MirSurface methods can still be accessed.
Q_EMIT destroyed(this);
}
QString MirSurface::name() const
{
return m_name;
}
QString MirSurface::persistentId() const
{
return m_name+"Id";
}
QString MirSurface::appId() const
{
return m_name+"appId";
}
Mir::Type MirSurface::type() const
{
return m_type;
}
Mir::State MirSurface::state() const
{
return m_state;
}
void MirSurface::requestState(Mir::State state)
{
if (state == m_state) {
return;
}
DEBUG_MSG(stateToStr(state));
Q_EMIT stateRequested(state);
}
void MirSurface::setState(Mir::State state)
{
if (state == m_state) {
return;
}
DEBUG_MSG(stateToStr(state));
bool oldVisible = visible();
m_state = state;
Q_EMIT stateChanged(state);
if (visible() != oldVisible) {
XDEBUG_MSG("visibleChanged("<count(); ++i) {
m_childSurfaceList->get(i)->close();
}
if (!m_zombieTimer.isActive()) {
m_zombieTimer.start();
Q_EMIT closeRequested();
}
}
void MirSurface::activate()
{
DEBUG_MSG("");
SurfaceManager::instance()->activate(this);
}
void MirSurface::requestFocus()
{
DEBUG_MSG("");
Q_EMIT focusRequested();
}
void MirSurface::setFocused(bool value)
{
if (m_focused == value)
return;
DEBUG_MSG("(" << value << ")");
m_focused = value;
Q_EMIT focusedChanged(value);
}
bool MirSurface::focused() const
{
return m_focused;
}
QRect MirSurface::inputBounds() const
{
return m_inputBounds;
}
void MirSurface::setInputBounds(const QRect &boundsRect)
{
if (boundsRect != m_inputBounds) {
m_inputBounds = boundsRect;
DEBUG_MSG("(" << m_inputBounds << ")");
Q_EMIT inputBoundsChanged(m_inputBounds);
}
}
void MirSurface::openMenu(qreal x, qreal y, qreal width, qreal height)
{
auto *menu = SurfaceManager::instance()->createSurface("menu", Mir::MenuType, Mir::HiddenState,
this /* parentSurface */,
QUrl() /* screenshot */,
QUrl("qrc:///Unity/Application/KateMenu.qml"));
menu->setRequestedPosition(QPoint(x,y));
menu->resize(width, height);
menu->requestState(Mir::RestoredState);
SurfaceManager::instance()->notifySurfaceCreated(menu);
}
void MirSurface::openDialog(qreal x, qreal y, qreal width, qreal height)
{
auto *dialog = SurfaceManager::instance()->createSurface("dialog", Mir::DialogType, Mir::HiddenState,
this /* parentSurface */,
QUrl() /* screenshot */,
QUrl("qrc:///Unity/Application/KateDialog.qml"));
dialog->setRequestedPosition(QPoint(x,y));
dialog->resize(width, height);
dialog->requestState(Mir::RestoredState);
SurfaceManager::instance()->notifySurfaceCreated(dialog);
dialog->requestFocus();
}
void MirSurface::setRequestedPosition(const QPoint &value)
{
if (value != m_requestedPosition) {
m_requestedPosition = value;
Q_EMIT requestedPositionChanged(value);
// fake-miral: always comply
m_position = m_requestedPosition;
XDEBUG_MSG("positionChanged("<