@@ -24,11 +24,16 @@
24#include <unity/shell/application/SurfaceManagerInterface.h>
24#include <unity/shell/application/SurfaceManagerInterface.h>
27−#include <QGuiApplication>
28#include <QDebug>
27#include <QDebug>
31#include "Window.h"
30#include "Window.h"
31+#include "Workspace.h"
32+#include "windowmanagementpolicy.h"
35+#include <qtmir/mirserverapplication.h>
36+#include <qtmir/windowmodelnotifier.h>
33Q_LOGGING_CATEGORY(TOPLEVELWINDOWMODEL, "toplevelwindowmodel", QtInfoMsg)
38Q_LOGGING_CATEGORY(TOPLEVELWINDOWMODEL, "toplevelwindowmodel", QtInfoMsg)
@@ -55,35 +60,24 @@ void TopLevelWindowModel::setApplicationManager(unityapi::ApplicationManagerInte
55 beginResetModel();
60 beginResetModel();
57 if (m_applicationManager) {
62 if (m_applicationManager) {
58− m_windowModel.clear();
59 disconnect(m_applicationManager, 0, this, 0);
63 disconnect(m_applicationManager, 0, this, 0);
62 m_applicationManager = value;
66 m_applicationManager = value;
64− if (m_applicationManager) {
68+ if (m_applicationManager && m_workspace) {
65− connect(m_applicationManager, &QAbstractItemModel::rowsInserted,
66− this, [this](const QModelIndex &/*parent*/, int first, int last) {
67− for (int i = first; i <= last; ++i) {
68− auto application = m_applicationManager->get(i);
69− addApplication(application);
73− connect(m_applicationManager, &QAbstractItemModel::rowsAboutToBeRemoved,
70+ if (m_workspace->isActive()) {
74− this, [this](const QModelIndex &/*parent*/, int first, int last) {
71+ connectApplicationManager();
75− for (int i = first; i <= last; ++i) {
76− auto application = m_applicationManager->get(i);
77− removeApplication(application);
81− for (int i = 0; i < m_applicationManager->rowCount(); ++i) {
74+ if (m_surfaceManager) {
82− auto application = m_applicationManager->get(i);
75+ refreshWindows();
83− addApplication(application);
79+ Q_EMIT applicationManagerChanged(m_applicationManager);
87 endResetModel();
81 endResetModel();
88 m_modelState = IdleState;
82 m_modelState = IdleState;
@@ -96,6 +90,11 @@ void TopLevelWindowModel::setSurfaceManager(unityapi::SurfaceManagerInterface *s
97 DEBUG_MSG << "(" << surfaceManager << ")";
91 DEBUG_MSG << "(" << surfaceManager << ")";
93+ Q_ASSERT(m_modelState == IdleState);
94+ m_modelState = ResettingState;
99 if (m_surfaceManager) {
98 if (m_surfaceManager) {
100 disconnect(m_surfaceManager, 0, this, 0);
99 disconnect(m_surfaceManager, 0, this, 0);
@@ -107,9 +106,68 @@ void TopLevelWindowModel::setSurfaceManager(unityapi::SurfaceManagerInterface *s
107 connect(m_surfaceManager, &unityapi::SurfaceManagerInterface::surfacesRaised, this, &TopLevelWindowModel::onSurfacesRaised);
106 connect(m_surfaceManager, &unityapi::SurfaceManagerInterface::surfacesRaised, this, &TopLevelWindowModel::onSurfacesRaised);
108 connect(m_surfaceManager, &unityapi::SurfaceManagerInterface::modificationsStarted, this, &TopLevelWindowModel::onModificationsStarted);
107 connect(m_surfaceManager, &unityapi::SurfaceManagerInterface::modificationsStarted, this, &TopLevelWindowModel::onModificationsStarted);
109 connect(m_surfaceManager, &unityapi::SurfaceManagerInterface::modificationsEnded, this, &TopLevelWindowModel::onModificationsEnded);
108 connect(m_surfaceManager, &unityapi::SurfaceManagerInterface::modificationsEnded, this, &TopLevelWindowModel::onModificationsEnded);
110+ connect(m_surfaceManager, &unityapi::SurfaceManagerInterface::surfacesAddedToWorkspace,
111+ this, &TopLevelWindowModel::onSurfacesAddedToWorkspace);
113+ if (m_workspace && m_applicationManager) {
112 Q_EMIT surfaceManagerChanged(m_surfaceManager);
118 Q_EMIT surfaceManagerChanged(m_surfaceManager);
121+ m_modelState = IdleState;
124+void TopLevelWindowModel::setWorkspace(Workspace *workspace)
126+ if (workspace == m_workspace) {
130+ DEBUG_MSG << "(" << workspace << ")";
132+ Q_ASSERT(m_modelState == IdleState);
133+ m_modelState = ResettingState;
138+ m_windowModel.clear();
139+ if (m_applicationManager) {
140+ disconnect(m_applicationManager, 0, this, 0);
144+ disconnect(m_applicationManager, 0 ,this, 0);
146+ m_workspace = workspace;
149+ connect(m_workspace, &Workspace::activeChanged, this, [this](bool active) {
150+ if (m_applicationManager) {
151+ if (!active) disconnect(m_applicationManager, 0, this, 0);
153+ connectApplicationManager();
158+ if (m_applicationManager && m_workspace->isActive()) {
159+ connectApplicationManager();
162+ if (m_surfaceManager && m_applicationManager) {
167+ Q_EMIT workspaceChanged(workspace);
170+ m_modelState = IdleState;
115void TopLevelWindowModel::addApplication(unityapi::ApplicationInfoInterface *application)
173void TopLevelWindowModel::addApplication(unityapi::ApplicationInfoInterface *application)
@@ -328,33 +386,43 @@ Window *TopLevelWindowModel::createWindow(unityapi::MirSurfaceInterface *surface
328 return qmlWindow;
386 return qmlWindow;
331−void TopLevelWindowModel::onSurfaceCreated(unityapi::MirSurfaceInterface *surface)
390+void TopLevelWindowModel::onSurfaceCreated(unityapi::MirSurfaceInterface */*surface*/)
333− DEBUG_MSG << "(" << surface << ")";
392+}
394+void TopLevelWindowModel::onSurfacesAddedToWorkspace(const std::shared_ptr<miral::Workspace>& workspace,
395+ const QVector<unity::shell::application::MirSurfaceInterface*> surfaces)
397+ if (workspace != m_workspace->workspace()) return;
399+ Q_FOREACH(auto surface, surfaces) {
400+ DEBUG_MSG << "(" << surface << ")";
335− if (surface->parentSurface()) {
402+ if (surface->parentSurface()) {
336− // Wrap it in a Window so that we keep focusedWindow() up to date.
403+ // Wrap it in a Window so that we keep focusedWindow() up to date.
337− Window *window = createWindow(surface);
404+ Window *window = createWindow(surface);
338− connect(surface, &QObject::destroyed, window, [=](){
405+ connect(surface, &QObject::destroyed, window, [=](){
339− window->setSurface(nullptr);
406+ window->setSurface(nullptr);
340− window->deleteLater();
407+ window->deleteLater();
343− if (surface->type() == Mir::InputMethodType) {
344− setInputMethodWindow(createWindow(surface));
346− auto *application = m_applicationManager->findApplicationWithSurface(surface);
410+ if (surface->type() == Mir::InputMethodType) {
347− if (application) {
411+ setInputMethodWindow(createWindow(surface));
348− prependSurface(surface, application);
413+ auto *application = m_applicationManager->findApplicationWithSurface(surface);
415+ prependSurface(surface, application);
350− // Must be a prompt session. No need to do add it as a prompt surface is not top-level.
417+ // Must be a prompt session. No need to do add it as a prompt surface is not top-level.
351− // It will show up in the ApplicationInfoInterface::promptSurfaceList of some application.
418+ // It will show up in the ApplicationInfoInterface::promptSurfaceList of some application.
352− // Still wrap it in a Window though, so that we keep focusedWindow() up to date.
419+ // Still wrap it in a Window though, so that we keep focusedWindow() up to date.
353− Window *promptWindow = createWindow(surface);
420+ Window *promptWindow = createWindow(surface);
354− connect(surface, &QObject::destroyed, promptWindow, [=](){
421+ connect(surface, &QObject::destroyed, promptWindow, [=](){
355− promptWindow->setSurface(nullptr);
422+ promptWindow->setSurface(nullptr);
356− promptWindow->deleteLater();
423+ promptWindow->deleteLater();
@@ -444,6 +512,26 @@ QVariant TopLevelWindowModel::data(const QModelIndex& index, int role) const
515+void TopLevelWindowModel::connectApplicationManager()
517+ connect(m_applicationManager, &QAbstractItemModel::rowsInserted,
518+ this, [this](const QModelIndex &/*parent*/, int first, int last) {
519+ for (int i = first; i <= last; ++i) {
520+ auto application = m_applicationManager->get(i);
521+ addApplication(application);
525+ connect(m_applicationManager, &QAbstractItemModel::rowsAboutToBeRemoved,
526+ this, [this](const QModelIndex &/*parent*/, int first, int last) {
527+ for (int i = first; i <= last; ++i) {
528+ auto application = m_applicationManager->get(i);
529+ removeApplication(application);
447int TopLevelWindowModel::findIndexOf(const unityapi::MirSurfaceInterface *surface) const
535int TopLevelWindowModel::findIndexOf(const unityapi::MirSurfaceInterface *surface) const
449 for (int i=0; i<m_windowModel.count(); i++) {
537 for (int i=0; i<m_windowModel.count(); i++) {
@@ -674,3 +762,39 @@ void TopLevelWindowModel::activateTopMostWindowWithoutId(int forbiddenId)
766+void TopLevelWindowModel::refreshWindows()
768+ m_windowModel.clear();
769+ WindowManagementPolicy::instance()->forEachWindowInWorkspace(m_workspace->workspace(), [this](const miral::Window &window) {
770+ auto surface = m_surfaceManager->surfaceFor(window);
772+ if (surface->parentSurface()) {
773+ // Wrap it in a Window so that we keep focusedWindow() up to date.
774+ Window *window = createWindow(surface);
775+ connect(surface, &QObject::destroyed, window, [=](){
776+ window->setSurface(nullptr);
777+ window->deleteLater();
780+ if (surface->type() == Mir::InputMethodType) {
781+ setInputMethodWindow(createWindow(surface));
783+ auto *application = m_applicationManager->findApplicationWithSurface(surface);
785+ prependSurface(surface, application);
787+ // Must be a prompt session. No need to do add it as a prompt surface is not top-level.
788+ // It will show up in the ApplicationInfoInterface::promptSurfaceList of some application.
789+ // Still wrap it in a Window though, so that we keep focusedWindow() up to date.
790+ Window *promptWindow = createWindow(surface);
791+ connect(surface, &QObject::destroyed, promptWindow, [=](){
792+ promptWindow->setSurface(nullptr);
793+ promptWindow->deleteLater();