on xenial help sign in
Make the DashCommunicator async and more flexible to handle a lifecycle-suspended dash Fixes: 1339883

Approved by: Albert Astals Cid

commitefcd1ba20a3a60108312fbcd130fed4a0538f1e6 authorMichael Zanetti <michael.zanetti@canonical.com> dateMon 6 Oct 2014, 08:00 (12 years ago) parent8e74cdd294d9b7
23 files changed+344−31
CMakeLists.txt+2−2 debian/control+1−1 debian/unity8-private.install+1 plugins/LightDM/DBusGreeter.h−1 plugins/LightDM/DBusGreeterList.h−1 plugins/Unity/DashCommunicator/CMakeLists.txt+8−2 plugins/Unity/DashCommunicator/dashcommunicator.cpp+22−13 plugins/Unity/DashCommunicator/dashcommunicator.h+16−6 plugins/Unity/DashCommunicator/dashconnection.cpp+33 plugins/Unity/DashCommunicator/dashconnection.h+34 plugins/Unity/Launcher/CMakeLists.txt+1−1 qml/Shell.qml+7 src/CMakeLists.txt+1 src/Dash/CMakeLists.txt+2 src/Panel/CMakeLists.txt+2 src/libunity8-private/CMakeLists.txt+25 src/libunity8-private/abstractdbusservicemonitor.cpp+87 src/libunity8-private/abstractdbusservicemonitor.h+66 tests/mocks/Unity/Application/ApplicationManager.cpp+26 tests/mocks/Unity/Application/ApplicationManager.h+6−2 tests/mocks/Unity/Application/CMakeLists.txt+1−1 tests/plugins/Unity/Launcher/CMakeLists.txt+1−1 tests/plugins/Unity/Launcher/launchermodeltest.cpp+2
CMakeLists.txt+2−2
@@ -64,13 +64,13 @@ if(SHELL_INSTALL_QML STREQUAL "")
6464 message(FATAL_ERROR "Could not determine plugin installation dir.")
6565endif()
6666
67+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden")
68+
6769execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE} --variable=plugindir unity-shell-api OUTPUT_VARIABLE SHELL_PLUGINDIR OUTPUT_STRIP_TRAILING_WHITESPACE)
6870if(SHELL_PLUGINDIR STREQUAL "")
6971 message(FATAL_ERROR "Could not determine plugin import dir.")
7072endif()
7173
72−set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden")
73−
7474set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-permissive -pedantic -Wall -Wextra")
7575
7676if ("${CMAKE_BUILD_TYPE}" STREQUAL "release" OR "${CMAKE_BUILD_TYPE}" STREQUAL "relwithdebinfo")
debian/control+1−1
@@ -25,7 +25,7 @@ Build-Depends: cmake,
2525 libpulse-dev,
2626 libqmenumodel-dev (>= 0.2.8),
2727 libqt5xmlpatterns5-dev,
28− libunity-api-dev (>= 7.91),
28+ libunity-api-dev (>= 7.92),
2929 libusermetricsoutput1-dev,
3030 libxcb1-dev,
3131 pkg-config,
debian/unity8-private.install+1
@@ -1,3 +1,4 @@
1+usr/lib/*/libunity8-private.*
12usr/lib/*/unity8/qml/AccountsService
23usr/lib/*/unity8/qml/Dash
34usr/lib/*/unity8/qml/HudClient
plugins/LightDM/DBusGreeter.h−1
@@ -21,7 +21,6 @@
2121#include <QObject>
2222
2323class Greeter;
24−class QDBusInterface;
2524
2625/** This is an internal class used to talk with the indicators.
2726 */
plugins/LightDM/DBusGreeterList.h−1
@@ -21,7 +21,6 @@
2121#include <QObject>
2222
2323class Greeter;
24−class QDBusInterface;
2524
2625/** This is an internal class used to talk with the indicators.
2726 */
plugins/Unity/DashCommunicator/CMakeLists.txt+8−2
@@ -1,5 +1,6 @@
11include_directories(
22 ${CMAKE_CURRENT_SOURCE_DIR}
3+ ${libunity8-private_SOURCE_DIR}
34)
45
56set(QMLDASHCOMMUNICATORPLUGIN_SRC
@@ -7,13 +8,18 @@ set(QMLDASHCOMMUNICATORPLUGIN_SRC
78 dbusdashcommunicatorservice.cpp
89 dashcommunicatorservice.cpp
910 dashcommunicator.cpp
10− )
11+ dashconnection.cpp
12+)
1113
1214add_library(DashCommunicator-qml MODULE
1315 ${QMLDASHCOMMUNICATORPLUGIN_SRC}
14− )
16+)
1517
1618qt5_use_modules(DashCommunicator-qml DBus Qml)
1719
20+target_link_libraries(DashCommunicator-qml
21+ unity8-private
22+)
23+
1824# export the qmldir and qmltypes files
1925add_unity8_plugin(Unity.DashCommunicator 0.1 Unity/DashCommunicator TARGETS DashCommunicator-qml)
plugins/Unity/DashCommunicator/dashcommunicator.cpp+22−13
@@ -15,29 +15,38 @@
1515 */
1616
1717#include "dashcommunicator.h"
18+#include "dashconnection.h"
1819
1920#include <QObject>
20−#include <QDBusConnection>
21−#include <QDBusInterface>
22−#include <QDebug>
2321
2422DashCommunicator::DashCommunicator(QObject *parent):
25− QObject(parent)
23+ QThread(parent),
24+ m_dashConnection(nullptr),
25+ m_created(false)
2626{
27+ start();
2728}
2829
29−DashCommunicator::~DashCommunicator()
30+void DashCommunicator::setCurrentScope(const QString &scopeId, bool animate, bool isSwipe)
3031{
32+ m_mutex.lock();
33+ if (m_created) {
34+ QMetaObject::invokeMethod(m_dashConnection, "setCurrentScope",
35+ Q_ARG(QString, scopeId),
36+ Q_ARG(bool, animate),
37+ Q_ARG(bool, isSwipe));
38+ }
39+ m_mutex.unlock();
3140}
3241
33−
34−void DashCommunicator::setCurrentScope(const QString &scopeId, bool animate, bool isSwipe)
42+void DashCommunicator::run()
3543{
36− QDBusConnection connection = QDBusConnection::sessionBus();
37− QDBusInterface dashIface ("com.canonical.UnityDash",
38− "/com/canonical/UnityDash",
39− "",
40− connection);
44+ m_dashConnection = new DashConnection("com.canonical.UnityDash",
45+ "/com/canonical/UnityDash",
46+ "", this);
47+ m_mutex.lock();
48+ m_created = true;
49+ m_mutex.unlock();
4150
42− dashIface.call("SetCurrentScope", scopeId, animate, isSwipe);
51+ exec();
4352}
plugins/Unity/DashCommunicator/dashcommunicator.h+16−6
@@ -17,19 +17,29 @@
1717#ifndef DASHCOMMUNICATOR_H
1818#define DASHCOMMUNICATOR_H
1919
20−#include <QObject>
20+// Qt
21+#include <QThread>
22+#include <QMutex>
2123
22−class DashCommunicator: public QObject
24+class DashConnection;
25+
26+class DashCommunicator: public QThread
2327{
2428 Q_OBJECT
25− Q_CLASSINFO("D-Bus Interface", "com.canonical.Unity.DashCommunicator")
26−
2729public:
28− DashCommunicator(QObject *parent = 0);
29− ~DashCommunicator();
30+ explicit DashCommunicator(QObject *parent = 0);
31+ ~DashCommunicator() = default;
3032
3133public Q_SLOTS:
3234 void setCurrentScope(const QString &scopeId, bool animate, bool isSwipe);
35+
36+protected:
37+ void run() override;
38+
39+private:
40+ DashConnection *m_dashConnection;
41+ bool m_created;
42+ QMutex m_mutex;
3343};
3444
3545#endif
plugins/Unity/DashCommunicator/dashconnection.cppnew file+33
@@ -0,0 +1,33 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it under
5+ * the terms of the GNU Lesser General Public License version 3, as published by
6+ * the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful, but WITHOUT
9+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11+ * Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include "dashconnection.h"
18+
19+#include <QDBusInterface>
20+#include <QDBusPendingCall>
21+
22+DashConnection::DashConnection(const QString &service, const QString &path, const QString &interface, QObject *parent):
23+ AbstractDBusServiceMonitor(service, path, interface, SessionBus, parent)
24+{
25+
26+}
27+
28+void DashConnection::setCurrentScope(const QString &scopeId, bool animate, bool isSwipe)
29+{
30+ if (dbusInterface()) {
31+ dbusInterface()->asyncCall("SetCurrentScope", scopeId, animate, isSwipe);
32+ }
33+}
plugins/Unity/DashCommunicator/dashconnection.hnew file+34
@@ -0,0 +1,34 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it under
5+ * the terms of the GNU Lesser General Public License version 3, as published by
6+ * the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful, but WITHOUT
9+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11+ * Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#ifndef THREADEDDASHCONNECTION_H
18+#define THREADEDDASHCONNECTION_H
19+
20+// local
21+#include "abstractdbusservicemonitor.h"
22+
23+
24+class DashConnection: public AbstractDBusServiceMonitor
25+{
26+ Q_OBJECT
27+public:
28+ DashConnection(const QString &service, const QString &path, const QString &interface, QObject *parent = 0);
29+
30+public Q_SLOTS:
31+ void setCurrentScope(const QString &scopeId, bool animate, bool isSwipe);
32+};
33+
34+#endif
plugins/Unity/Launcher/CMakeLists.txt+1−1
@@ -1,6 +1,6 @@
11include(FindPkgConfig)
22pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=4)
3−pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=4)
3+pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=5)
44pkg_check_modules(GSETTINGS_QT REQUIRED gsettings-qt)
55
66add_definitions(-DSM_BUSNAME=systemBus)
qml/Shell.qml+7
@@ -128,6 +128,13 @@ Item {
128128 objectName: "dashCommunicator"
129129 }
130130
131+ Binding {
132+ target: ApplicationManager
133+ property: "forceDashActive"
134+ value: launcher.shown || launcher.dashSwipe
135+ }
136+
137+
131138 WindowKeysFilter {
132139 // Handle but do not filter out volume keys
133140 Keys.onVolumeUpPressed: { volumeControl.volumeUp(); event.accepted = false; }
src/CMakeLists.txt+1
@@ -36,3 +36,4 @@ install(TARGETS ${SHELL_APP}
3636
3737add_subdirectory(Panel)
3838add_subdirectory(Dash)
39+add_subdirectory(libunity8-private)
src/Dash/CMakeLists.txt+2
@@ -9,6 +9,8 @@ add_executable(unity8-dash ${DASH_SRCS})
99
1010qt5_use_modules(unity8-dash Gui Qml Quick Test)
1111
12+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden")
13+
1214# install binaries
1315install(TARGETS ${DASH_APP}
1416 RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
src/Panel/CMakeLists.txt+2
@@ -1 +1,3 @@
11add_subdirectory(Indicators)
2+
3+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden")
src/libunity8-private/CMakeLists.txtnew file+25
@@ -0,0 +1,25 @@
1+set(LIB_NAME "unity8-private")
2+set(SOVERSION 0)
3+set(VERSION ${SOVERSION}.0.0)
4+
5+project(lib${LIB_NAME})
6+
7+set(lib${LIB_NAME}_SRCS
8+ abstractdbusservicemonitor.cpp
9+ )
10+
11+add_library(${LIB_NAME} SHARED
12+ ${lib${LIB_NAME}_SRCS}
13+ )
14+
15+set_target_properties(${LIB_NAME} PROPERTIES
16+ VERSION ${VERSION}
17+ SOVERSION ${SOVERSION}
18+ )
19+
20+qt5_use_modules(${LIB_NAME} DBus)
21+
22+# install library
23+install(TARGETS ${LIB_NAME}
24+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
25+ )
src/libunity8-private/abstractdbusservicemonitor.cppnew file+87
@@ -0,0 +1,87 @@
1+/*
2+ * Copyright (C) 2011-2014 Canonical, Ltd.
3+ *
4+ * Authors:
5+ * Ugo Riboni <ugo.riboni@canonical.com>
6+ *
7+ * This program is free software; you can redistribute it and/or modify
8+ * it under the terms of the GNU General Public License as published by
9+ * the Free Software Foundation; version 3.
10+ *
11+ * This program is distributed in the hope that it will be useful,
12+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ * GNU General Public License for more details.
15+ *
16+ * You should have received a copy of the GNU General Public License
17+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
18+ */
19+
20+#include "abstractdbusservicemonitor.h"
21+
22+#include <QDBusInterface>
23+#include <QDBusServiceWatcher>
24+#include <QDBusConnection>
25+#include <QDBusConnectionInterface>
26+#include <QDBusReply>
27+
28+AbstractDBusServiceMonitor::AbstractDBusServiceMonitor(const QString &service, const QString &path,
29+ const QString &interface, const Bus bus,
30+ QObject *parent)
31+ : QObject(parent)
32+ , m_service(service)
33+ , m_path(path)
34+ , m_interface(interface)
35+ , m_watcher(new QDBusServiceWatcher(service,
36+ (bus == SystemBus) ? QDBusConnection::systemBus()
37+ : QDBusConnection::sessionBus()))
38+ , m_dbusInterface(nullptr)
39+{
40+ connect(m_watcher, &QDBusServiceWatcher::serviceRegistered, this, &AbstractDBusServiceMonitor::createInterface);
41+ connect(m_watcher, &QDBusServiceWatcher::serviceUnregistered, this, &AbstractDBusServiceMonitor::destroyInterface);
42+
43+ // Connect to the service if it's up already
44+ QDBusConnectionInterface* sessionBus = QDBusConnection::sessionBus().interface();
45+ QDBusReply<bool> reply = sessionBus->isServiceRegistered(m_service);
46+ if (reply.isValid() && reply.value()) {
47+ createInterface(m_service);
48+ }
49+}
50+
51+AbstractDBusServiceMonitor::~AbstractDBusServiceMonitor()
52+{
53+ delete m_watcher;
54+ delete m_dbusInterface;
55+}
56+
57+void AbstractDBusServiceMonitor::createInterface(const QString &)
58+{
59+ if (m_dbusInterface != nullptr) {
60+ delete m_dbusInterface;
61+ m_dbusInterface = nullptr;
62+ }
63+
64+ m_dbusInterface = new QDBusInterface(m_service, m_path, m_interface,
65+ QDBusConnection::sessionBus());
66+ Q_EMIT serviceAvailableChanged(true);
67+}
68+
69+void AbstractDBusServiceMonitor::destroyInterface(const QString &)
70+{
71+ if (m_dbusInterface != nullptr) {
72+ delete m_dbusInterface;
73+ m_dbusInterface = nullptr;
74+ }
75+
76+ Q_EMIT serviceAvailableChanged(false);
77+}
78+
79+QDBusInterface* AbstractDBusServiceMonitor::dbusInterface() const
80+{
81+ return m_dbusInterface;
82+}
83+
84+bool AbstractDBusServiceMonitor::serviceAvailable() const
85+{
86+ return m_dbusInterface != nullptr;
87+}
src/libunity8-private/abstractdbusservicemonitor.hnew file+66
@@ -0,0 +1,66 @@
1+/*
2+ * Copyright (C) 2011-2014 Canonical, Ltd.
3+ *
4+ * Authors:
5+ * Ugo Riboni <ugo.riboni@canonical.com>
6+ *
7+ * This program is free software; you can redistribute it and/or modify
8+ * it under the terms of the GNU General Public License as published by
9+ * the Free Software Foundation; version 3.
10+ *
11+ * This program is distributed in the hope that it will be useful,
12+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ * GNU General Public License for more details.
15+ *
16+ * You should have received a copy of the GNU General Public License
17+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
18+ */
19+
20+#ifndef ABSTRACTDBUSSERVICEMONITOR_H
21+#define ABSTRACTDBUSSERVICEMONITOR_H
22+
23+#include <QObject>
24+#include <QString>
25+#include <QDBusConnection>
26+
27+class QDBusInterface;
28+class QDBusServiceWatcher;
29+
30+class Q_DECL_EXPORT AbstractDBusServiceMonitor : public QObject
31+{
32+ Q_OBJECT
33+ Q_ENUMS(Bus)
34+ Q_PROPERTY(bool serviceAvailable READ serviceAvailable NOTIFY serviceAvailableChanged)
35+
36+public:
37+ enum Bus {
38+ SessionBus,
39+ SystemBus,
40+ };
41+
42+ explicit AbstractDBusServiceMonitor(const QString &service, const QString &path, const QString &interface,
43+ const Bus bus = SessionBus,
44+ QObject *parent = 0);
45+ ~AbstractDBusServiceMonitor();
46+
47+ QDBusInterface* dbusInterface() const;
48+
49+ bool serviceAvailable() const;
50+
51+Q_SIGNALS:
52+ void serviceAvailableChanged(bool available);
53+
54+private Q_SLOTS:
55+ void createInterface(const QString &service);
56+ void destroyInterface(const QString &service);
57+
58+protected:
59+ const QString m_service;
60+ const QString m_path;
61+ const QString m_interface;
62+ QDBusServiceWatcher* m_watcher;
63+ QDBusInterface* m_dbusInterface;
64+};
65+
66+#endif // ABSTRACTDBUSSERVICEMONITOR_H
tests/mocks/Unity/Application/ApplicationManager.cpp+26
@@ -43,6 +43,7 @@ ApplicationManager *ApplicationManager::singleton()
4343ApplicationManager::ApplicationManager(QObject *parent)
4444 : ApplicationManagerInterface(parent)
4545 , m_suspended(false)
46+ , m_forceDashActive(false)
4647{
4748 m_roleNames.insert(RoleSession, "session");
4849 m_roleNames.insert(RoleFullscreen, "fullscreen");
@@ -292,6 +293,31 @@ void ApplicationManager::setSuspended(bool suspended)
292293 Q_EMIT suspendedChanged();
293294}
294295
296+bool ApplicationManager::forceDashActive() const
297+{
298+ return m_forceDashActive;
299+}
300+
301+void ApplicationManager::setForceDashActive(bool forceDashActive)
302+{
303+ if (m_forceDashActive == forceDashActive) {
304+ return;
305+ }
306+
307+ ApplicationInfo *dash = findApplication("unity8-dash");
308+ if (dash) {
309+ if (forceDashActive) {
310+ dash->setState(ApplicationInfo::Running);
311+ } else {
312+ if (!dash->focused()) {
313+ dash->setState(ApplicationInfo::Suspended);
314+ }
315+ }
316+ }
317+ m_forceDashActive = forceDashActive;
318+ Q_EMIT forceDashActiveChanged();
319+}
320+
295321bool ApplicationManager::focusApplication(const QString &appId)
296322{
297323 ApplicationInfo *application = findApplication(appId);
tests/mocks/Unity/Application/ApplicationManager.h+6−2
@@ -99,8 +99,11 @@ class ApplicationManager : public ApplicationManagerInterface {
9999 Q_INVOKABLE bool stopApplication(const QString &appId) override;
100100
101101 QString focusedApplicationId() const override;
102− bool suspended() const;
103− void setSuspended(bool suspended);
102+ bool suspended() const override;
103+ void setSuspended(bool suspended) override;
104+
105+ bool forceDashActive() const override;
106+ void setForceDashActive(bool forceDashActive) override;
104107
105108 // Only for testing
106109 Q_INVOKABLE QStringList availableApplications();
@@ -124,6 +127,7 @@ class ApplicationManager : public ApplicationManagerInterface {
124127 void buildListOfAvailableApplications();
125128 void onWindowCreated();
126129 bool m_suspended;
130+ bool m_forceDashActive;
127131 QList<ApplicationInfo*> m_runningApplications;
128132 QList<ApplicationInfo*> m_availableApplications;
129133 QTimer m_windowCreatedTimer;
tests/mocks/Unity/Application/CMakeLists.txt+1−1
@@ -1,4 +1,4 @@
1−pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=4)
1+pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=5)
22
33set(FakeUnityApplicationQml_SOURCES
44 plugin.cpp
tests/plugins/Unity/Launcher/CMakeLists.txt+1−1
@@ -1,6 +1,6 @@
11pkg_check_modules(GSETTINGS_QT REQUIRED gsettings-qt)
22pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=4)
3−pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=4)
3+pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=5)
44
55include_directories(
66 ${CMAKE_CURRENT_BINARY_DIR}
tests/plugins/Unity/Launcher/launchermodeltest.cpp+2
@@ -105,6 +105,8 @@ public:
105105 bool requestFocusApplication(const QString &appId) { Q_UNUSED(appId); return true; }
106106 bool suspended() const { return false; }
107107 void setSuspended(bool) {}
108+ bool forceDashActive() const { return false; }
109+ void setForceDashActive(bool) {}
108110
109111private:
110112 QList<MockApp*> m_list;