2 * Copyright (C) 2014-2016 Canonical, Ltd.
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.
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.
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/>.
17#include "SurfaceManager.h"
19#include "ApplicationInfo.h"
20#include "VirtualKeyboard.h"
21#include "../../WindowManager/WindowManagementPolicy.h"
24#include <mirtest/mir/test/doubles/stub_surface.h>
26#define SURFACEMANAGER_DEBUG 1
28#if SURFACEMANAGER_DEBUG
29#define DEBUG_MSG(params) qDebug().nospace() << "SurfaceManager[" << (void*)this << "]::" << __func__ << params
31#define DEBUG_MSG(params) ((void)0)
34namespace unityapi = unity::shell::application;
36uint qHash(const WindowWrapper &key, uint)
38 std::shared_ptr<mir::scene::Surface> surface = key.window;
39 return (quintptr)surface.get();
42SurfaceManager *SurfaceManager::m_instance = nullptr;
44SurfaceManager *SurfaceManager::instance()
49SurfaceManager::SurfaceManager(QObject *)
53 Q_ASSERT(m_instance == nullptr);
56 connect(WindowManagementPolicy::instance(), &WindowManagementPolicy::windowAdded,
57 this, [this](const miral::Window& window) {
58 Q_EMIT surfaceCreated(surfaceFor(window));
61 connect(WindowManagementPolicy::instance(), &WindowManagementPolicy::windowsAddedToWorkspace,
62 this, [this](const std::shared_ptr<miral::Workspace> &workspace, const std::vector<miral::Window> &windows) {
63 Q_EMIT surfacesAddedToWorkspace(workspace, surfacesFor(windows));
66 connect(WindowManagementPolicy::instance(), &WindowManagementPolicy::windowsAboutToBeRemovedFromWorkspace,
67 this, [this](const std::shared_ptr<miral::Workspace> &workspace, const std::vector<miral::Window> &windows) {
68 Q_EMIT surfacesAboutToBeRemovedFromWorkspace(workspace, surfacesFor(windows));
72SurfaceManager::~SurfaceManager()
76 if (m_virtualKeyboard) {
77 m_virtualKeyboard->setLive(false);
80 Q_ASSERT(m_instance == this);
84MirSurfaceInterface *SurfaceManager::surfaceFor(const miral::Window& window) const
86 auto iter = m_windowToSurface.find({window});
87 if (iter != m_windowToSurface.end()) {
93QVector<MirSurfaceInterface*> SurfaceManager::surfacesFor(const std::vector<miral::Window> &windows) const
95 QVector<unityapi::MirSurfaceInterface*> surfaces;
96 for (size_t i = 0; i < windows.size(); i++) {
97 auto mirSurface = surfaceFor(windows[i]);
99 surfaces.push_back(mirSurface);
105miral::Window SurfaceManager::windowFor(MirSurfaceInterface *surface) const
107 auto iter = m_surfaceToWindow.find(surface);
108 if (iter != m_surfaceToWindow.end()) {
111 return miral::Window();
114MirSurface *SurfaceManager::createSurface(const QString& name,
117 MirSurface *parentSurface,
118 const QUrl &screenshot,
119 const QUrl &qmlFilePath)
121 MirSurface* surface = new MirSurface(name, type, state, parentSurface, screenshot, qmlFilePath);
122 registerSurface(surface);
124 static_cast<MirSurfaceListModel*>(parentSurface->childSurfaceList())->addSurface(surface);
129void SurfaceManager::registerSurface(MirSurface *surface)
131 auto fakeSurface = std::make_shared<mir::test::doubles::StubSurface>();
132 WindowWrapper window{miral::Window(nullptr, fakeSurface), fakeSurface};
134 m_surfaces.prepend(surface);
135 m_windowToSurface.insert(window, surface);
136 m_surfaceToWindow.insert(surface, window);
138 if (!surface->parentSurface()) {
139 surface->setMinimumWidth(m_newSurfaceMinimumWidth);
140 surface->setMaximumWidth(m_newSurfaceMaximumWidth);
141 surface->setMinimumHeight(m_newSurfaceMinimumHeight);
142 surface->setMaximumHeight(m_newSurfaceMaximumHeight);
143 surface->setWidthIncrement(m_newSurfaceWidthIncrement);
144 surface->setHeightIncrement(m_newSurfaceHeightIncrement);
147 connect(surface, &MirSurface::stateRequested, this, [=](Mir::State state) {
148 this->onStateRequested(surface, state);
151 const QString persistentId = surface->persistentId();
152 connect(surface, &QObject::destroyed, this, [=]() {
153 WindowWrapper key = m_surfaceToWindow.take(surface);
154 m_windowToSurface.remove(key);
155 this->onSurfaceDestroyed(surface, persistentId);
160void SurfaceManager::notifySurfaceCreated(unityapi::MirSurfaceInterface *surface)
162 if (Q_UNLIKELY(!m_surfaceToWindow.contains(surface))) {
163 Q_EMIT surfaceCreated(surface);
167 WindowManagementPolicy::instance()->addWindow(m_surfaceToWindow[surface].window);
170void SurfaceManager::setNewSurfaceMinimumWidth(int value)
172 if (m_newSurfaceMinimumWidth != value) {
173 m_newSurfaceMinimumWidth = value;
174 Q_EMIT newSurfaceMinimumWidthChanged(m_newSurfaceMinimumWidth);
178void SurfaceManager::setNewSurfaceMaximumWidth(int value)
180 if (m_newSurfaceMaximumWidth != value) {
181 m_newSurfaceMaximumWidth = value;
182 Q_EMIT newSurfaceMaximumWidthChanged(m_newSurfaceMaximumWidth);
186void SurfaceManager::setNewSurfaceMinimumHeight(int value)
188 if (m_newSurfaceMinimumHeight != value) {
189 m_newSurfaceMinimumHeight = value;
190 Q_EMIT newSurfaceMinimumHeightChanged(m_newSurfaceMinimumHeight);
194void SurfaceManager::setNewSurfaceMaximumHeight(int value)
196 if (m_newSurfaceMaximumHeight != value) {
197 m_newSurfaceMaximumHeight = value;
198 Q_EMIT newSurfaceMaximumHeightChanged(m_newSurfaceMaximumHeight);
202void SurfaceManager::setNewSurfaceWidthIncrement(int value)
204 if (m_newSurfaceWidthIncrement != value) {
205 m_newSurfaceWidthIncrement = value;
206 Q_EMIT newSurfaceWidthIncrementChanged(m_newSurfaceWidthIncrement);
210void SurfaceManager::setNewSurfaceHeightIncrement(int value)
212 if (m_newSurfaceHeightIncrement != value) {
213 m_newSurfaceHeightIncrement = value;
214 Q_EMIT newSurfaceHeightIncrementChanged(m_newSurfaceHeightIncrement);
218void SurfaceManager::raise(unityapi::MirSurfaceInterface *surface)
220 if (m_underModification)
223 DEBUG_MSG("("<<surface<<") started");
224 Q_EMIT modificationsStarted();
225 m_underModification = true;
229 m_underModification = false;
230 Q_EMIT modificationsEnded();
231 DEBUG_MSG("("<<surface<<") ended");
234void SurfaceManager::doRaise(unityapi::MirSurfaceInterface *apiSurface)
236 auto surface = static_cast<MirSurface*>(apiSurface);
237 int index = m_surfaces.indexOf(surface);
238 Q_ASSERT(index != -1);
239 m_surfaces.move(index, 0);
241 Q_EMIT surfacesRaised({surface});
244void SurfaceManager::activate(unityapi::MirSurfaceInterface *apiSurface)
246 auto surface = static_cast<MirSurface*>(apiSurface);
248 if (surface == m_focusedSurface) {
252 Q_ASSERT(!m_underModification);
254 DEBUG_MSG("("<<surface<<") started");
255 Q_EMIT modificationsStarted();
256 m_underModification = true;
257 if (m_focusedSurface) {
258 m_focusedSurface->setFocused(false);
261 if (surface->state() == Mir::HiddenState || surface->state() == Mir::MinimizedState) {
262 if (surface->previousState() != Mir::UnknownState) {
263 surface->setState(surface->previousState());
265 surface->setState(Mir::RestoredState);
268 surface->setFocused(true);
271 m_focusedSurface = surface;
272 m_underModification = false;
273 Q_EMIT modificationsEnded();
274 DEBUG_MSG("("<<surface<<") ended");
277void SurfaceManager::forEachSurfaceInWorkspace(const std::shared_ptr<miral::Workspace> &workspace,
278 const std::function<void(unity::shell::application::MirSurfaceInterface*)> &callback)
280 WindowManagementPolicy::instance()->forEachWindowInWorkspace(workspace, [&](const miral::Window &window) {
281 auto surface = surfaceFor(window);
288void SurfaceManager::moveSurfaceToWorkspace(unity::shell::application::MirSurfaceInterface* surface,
289 const std::shared_ptr<miral::Workspace> &workspace)
291 auto window = windowFor(surface);
293 WindowManagementPolicy::instance()->moveWindowToWorkspace(window, workspace);
297void SurfaceManager::moveWorkspaceContentToWorkspace(const std::shared_ptr<miral::Workspace> &to,
298 const std::shared_ptr<miral::Workspace> &from)
300 WindowManagementPolicy::instance()->moveWorkspaceContentToWorkspace(to, from);
303void SurfaceManager::onStateRequested(MirSurface *surface, Mir::State state)
305 DEBUG_MSG("("<<surface<<","<<state<<") started");
306 Q_EMIT modificationsStarted();
307 m_underModification = true;
309 surface->setPreviousState(surface->state());
310 surface->setState(state);
312 if ((state == Mir::MinimizedState || state == Mir::HiddenState) && surface->focused()) {
313 Q_ASSERT(m_focusedSurface == surface);
314 surface->setFocused(false);
315 m_focusedSurface = nullptr;
316 focusFirstAvailableSurface();
319 m_underModification = false;
320 Q_EMIT modificationsEnded();
321 DEBUG_MSG("("<<surface<<","<<state<<") ended");
324void SurfaceManager::onSurfaceDestroyed(MirSurface *surface, const QString& persistentId)
326 m_surfaces.removeAll(surface);
327 if (m_focusedSurface == surface) {
328 m_focusedSurface = nullptr;
330 Q_EMIT modificationsStarted();
331 m_underModification = true;
333 focusFirstAvailableSurface();
335 m_underModification = false;
336 Q_EMIT modificationsEnded();
338 Q_EMIT surfaceDestroyed(persistentId);
341void SurfaceManager::focusFirstAvailableSurface()
343 MirSurface *chosenSurface = nullptr;
344 for (int i = 0; i < m_surfaces.count() && !chosenSurface; ++i) {
345 auto *surface = m_surfaces[i];
346 if (surface->state() != Mir::HiddenState && surface->state() != Mir::MinimizedState) {
347 chosenSurface = surface;
351 if (!chosenSurface) {
355 if (m_focusedSurface) {
356 m_focusedSurface->setFocused(false);
359 chosenSurface->setFocused(true);
360 doRaise(chosenSurface);
362 m_focusedSurface = chosenSurface;
365void SurfaceManager::createInputMethodSurface()
367 if (!m_virtualKeyboard) {
368 m_virtualKeyboard = new VirtualKeyboard;
369 registerSurface(m_virtualKeyboard);
370 Q_EMIT surfaceCreated(m_virtualKeyboard);
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list