on xenial help sign in
Fix the mess I made with the lifecycle of the mock Unity.Application singletons
8144053Daniel d'Andrada
tests/mocks/Unity/Application/ApplicationInfo.cpp+3
@@ -50,6 +50,8 @@ QString stateToStr(ApplicationInfo::State state)
50#define DEBUG_MSG(params) ((void)0)
50#define DEBUG_MSG(params) ((void)0)
51#endif
51#endif
52
52
53+#define WARNING_MSG(params) qWarning().nospace() << "Application["<<appId()<<"]::" << __func__ << " " << params
54+
53ApplicationInfo::ApplicationInfo(const QString &appId, QObject *parent)
55ApplicationInfo::ApplicationInfo(const QString &appId, QObject *parent)
54 : ApplicationInfoInterface(appId, parent)
56 : ApplicationInfoInterface(appId, parent)
55 , m_appId(appId)
57 , m_appId(appId)
@@ -82,6 +84,7 @@ void ApplicationInfo::createSurface()
82
84
83 auto surfaceManager = SurfaceManager::instance();
85 auto surfaceManager = SurfaceManager::instance();
84 if (!surfaceManager) {
86 if (!surfaceManager) {
87+ WARNING_MSG("No SurfaceManager");
85 return;
88 return;
86 }
89 }
87
90
tests/mocks/Unity/Application/ApplicationManager.cpp+2−16
@@ -40,25 +40,10 @@
40
40
41namespace unityapi = unity::shell::application;
41namespace unityapi = unity::shell::application;
42
42
43−ApplicationManager *ApplicationManager::the_application_manager = nullptr;
44−
45−ApplicationManager *ApplicationManager::singleton()
46−{
47− if (!the_application_manager) {
48− the_application_manager = new ApplicationManager();
49−
50− // Emit signal to notify Upstart that Mir is ready to receive client connections
51− // see http://upstart.ubuntu.com/cookbook/#expect-stop
52− if (qgetenv("UNITY_MIR_EMITS_SIGSTOP") == "1") {
53− raise(SIGSTOP);
54− }
55− }
56− return the_application_manager;
57−}
58−
59ApplicationManager::ApplicationManager(QObject *parent)
43ApplicationManager::ApplicationManager(QObject *parent)
60 : ApplicationManagerInterface(parent)
44 : ApplicationManagerInterface(parent)
61{
45{
46+ DEBUG_MSG("");
62 buildListOfAvailableApplications();
47 buildListOfAvailableApplications();
63
48
64 // polling to find out when the toplevel window has been created as there's
49 // polling to find out when the toplevel window has been created as there's
@@ -68,6 +53,7 @@ ApplicationManager::ApplicationManager(QObject *parent)
68 m_windowCreatedTimer.setSingleShot(false);
53 m_windowCreatedTimer.setSingleShot(false);
69 m_windowCreatedTimer.start(200);
54 m_windowCreatedTimer.start(200);
70
55
56+ Q_ASSERT(MirFocusController::instance());
71 connect(MirFocusController::instance(), &MirFocusController::focusedSurfaceChanged,
57 connect(MirFocusController::instance(), &MirFocusController::focusedSurfaceChanged,
72 this, &ApplicationManager::updateFocusedApplication, Qt::QueuedConnection);
58 this, &ApplicationManager::updateFocusedApplication, Qt::QueuedConnection);
73}
59}
tests/mocks/Unity/Application/ApplicationManager.h−4
@@ -47,8 +47,6 @@ class ApplicationManager : public ApplicationManagerInterface {
47 ApplicationManager(QObject *parent = nullptr);
47 ApplicationManager(QObject *parent = nullptr);
48 virtual ~ApplicationManager();
48 virtual ~ApplicationManager();
49
49
50− static ApplicationManager *singleton();
51−
52 // QAbstractItemModel methods.
50 // QAbstractItemModel methods.
53 int rowCount(const QModelIndex& parent = QModelIndex()) const override;
51 int rowCount(const QModelIndex& parent = QModelIndex()) const override;
54 QVariant data(const QModelIndex& index, int role) const override;
52 QVariant data(const QModelIndex& index, int role) const override;
@@ -90,8 +88,6 @@ class ApplicationManager : public ApplicationManagerInterface {
90 QList<ApplicationInfo*> m_runningApplications;
88 QList<ApplicationInfo*> m_runningApplications;
91 QList<ApplicationInfo*> m_availableApplications;
89 QList<ApplicationInfo*> m_availableApplications;
92 QTimer m_windowCreatedTimer;
90 QTimer m_windowCreatedTimer;
93−
94− static ApplicationManager *the_application_manager;
95};
91};
96
92
97Q_DECLARE_METATYPE(ApplicationManager*)
93Q_DECLARE_METATYPE(ApplicationManager*)
tests/mocks/Unity/Application/MirSurface.cpp+4
@@ -93,6 +93,7 @@ MirSurface::~MirSurface()
93{
93{
94 DEBUG_MSG("");
94 DEBUG_MSG("");
95
95
96+ // controller instance might have been already destroyed by QQmlEngine destructor
96 auto controller = MirFocusController::instance();
97 auto controller = MirFocusController::instance();
97 if (controller && controller->focusedSurface() == this) {
98 if (controller && controller->focusedSurface() == this) {
98 controller->clear();
99 controller->clear();
@@ -437,6 +438,7 @@ void MirSurface::setFocused(bool value)
437 DEBUG_MSG(value);
438 DEBUG_MSG(value);
438
439
439 auto controller = MirFocusController::instance();
440 auto controller = MirFocusController::instance();
441+ // controller instance might have been already destroyed by QQmlEngine destructor
440 if (!controller) {
442 if (!controller) {
441 return;
443 return;
442 }
444 }
@@ -452,6 +454,7 @@ bool MirSurface::focused() const
452{
454{
453 auto controller = MirFocusController::instance();
455 auto controller = MirFocusController::instance();
454
456
457+ // controller instance might have been already destroyed by QQmlEngine destructor
455 return controller ? controller->focusedSurface() == this : false;
458 return controller ? controller->focusedSurface() == this : false;
456}
459}
457
460
@@ -490,6 +493,7 @@ MirFocusController* MirFocusController::instance()
490
493
491MirFocusController::MirFocusController()
494MirFocusController::MirFocusController()
492{
495{
496+ DEBUG_MSG("");
493 Q_ASSERT(m_instance == nullptr);
497 Q_ASSERT(m_instance == nullptr);
494 m_instance = this;
498 m_instance = this;
495}
499}
tests/mocks/Unity/Application/UbuntuKeyboardInfo.cpp−2
@@ -16,8 +16,6 @@
16
16
17#include "UbuntuKeyboardInfo.h"
17#include "UbuntuKeyboardInfo.h"
18
18
19−UbuntuKeyboardInfo *UbuntuKeyboardInfo::m_instance = nullptr;
20−
21UbuntuKeyboardInfo::UbuntuKeyboardInfo(QObject *parent)
19UbuntuKeyboardInfo::UbuntuKeyboardInfo(QObject *parent)
22 : QObject(parent),
20 : QObject(parent),
23 m_x(0),
21 m_x(0),
tests/mocks/Unity/Application/UbuntuKeyboardInfo.h−9
@@ -40,13 +40,6 @@ public:
40 void setWidth(qreal value);
40 void setWidth(qreal value);
41 void setHeight(qreal value);
41 void setHeight(qreal value);
42
42
43− static UbuntuKeyboardInfo *singleton() {
44− if (!m_instance) {
45− m_instance = new UbuntuKeyboardInfo;
46− }
47− return m_instance;
48− }
49−
50Q_SIGNALS:
43Q_SIGNALS:
51 void xChanged(qreal x);
44 void xChanged(qreal x);
52 void yChanged(qreal y);
45 void yChanged(qreal y);
@@ -59,8 +52,6 @@ private:
59 qint32 m_y;
52 qint32 m_y;
60 qint32 m_width;
53 qint32 m_width;
61 qint32 m_height;
54 qint32 m_height;
62−
63− static UbuntuKeyboardInfo *m_instance;
64};
55};
65
56
66#endif // UBUNTU_KEYBOARD_INFO_H
57#endif // UBUNTU_KEYBOARD_INFO_H
tests/mocks/Unity/Application/plugin.cpp+31−14
@@ -27,29 +27,46 @@
27#include <qqml.h>
27#include <qqml.h>
28#include <QQmlEngine>
28#include <QQmlEngine>
29
29
30+namespace {
31+
32+// Creates the singletons that are called throughout C++ code
33+void createUnityApplicationSharedSingletons()
34+{
35+ // they have to be created in a specific order
36+ if (!MirFocusController::instance()) {
37+ new MirFocusController;
38+ }
39+ if (!SurfaceManager::instance()) {
40+ new SurfaceManager;
41+ }
42+}
43+
30−static QObject* applicationManagerSingleton(QQmlEngine* engine, QJSEngine* scriptEngine) {
44+QObject* applicationManagerSingleton(QQmlEngine*, QJSEngine*)
31− Q_UNUSED(engine);
45+{
32− Q_UNUSED(scriptEngine);
46+ createUnityApplicationSharedSingletons();
33− return ApplicationManager::singleton();
47+ return new ApplicationManager;
34}
48}
35
49
36−static QObject* surfaceManagerSingleton(QQmlEngine* engine, QJSEngine* scriptEngine) {
50+QObject* surfaceManagerSingleton(QQmlEngine*, QJSEngine*)
37− Q_UNUSED(engine);
51+{
38− Q_UNUSED(scriptEngine);
52+ createUnityApplicationSharedSingletons();
39− // QQmlEngine takes ownership over it (ie, it's deleted on ~QQmlEngine)
40− return new SurfaceManager;
53+ return SurfaceManager::instance();
41}
54}
42
55
43−static QObject* ubuntuKeyboardInfoSingleton(QQmlEngine*, QJSEngine*) {
56+QObject* ubuntuKeyboardInfoSingleton(QQmlEngine*, QJSEngine*)
57+{
58+ createUnityApplicationSharedSingletons();
44− return UbuntuKeyboardInfo::singleton();
59+ return new UbuntuKeyboardInfo;
45}
60}
46
61
47−static QObject* mirFocusControllerSingleton(QQmlEngine*, QJSEngine*)
62+QObject* mirFocusControllerSingleton(QQmlEngine*, QJSEngine*)
48{
63{
49− // QQmlEngine takes ownership over it (ie, it's deleted on ~QQmlEngine)
64+ createUnityApplicationSharedSingletons();
50− return new MirFocusController;
65+ return MirFocusController::instance();
51}
66}
52
67
68+} // anonymous namespace
69+
53void FakeUnityApplicationQmlPlugin::registerTypes(const char *uri)
70void FakeUnityApplicationQmlPlugin::registerTypes(const char *uri)
54{
71{
55 qRegisterMetaType<ApplicationInfo*>("ApplicationInfo*");
72 qRegisterMetaType<ApplicationInfo*>("ApplicationInfo*");