Merge lp:~mterry/unity8/gnome-session-quit into lp:unity8

Proposed by Michael Terry
Status: Merged
Approved by: Albert Astals Cid
Approved revision: 2870
Merged at revision: 2869
Proposed branch: lp:~mterry/unity8/gnome-session-quit
Merge into: lp:unity8
Diff against target: 291 lines (+186/-8)
6 files modified
plugins/Unity/Session/dbusunitysessionservice.cpp (+46/-1)
plugins/Unity/Session/dbusunitysessionservice.h (+18/-4)
tests/plugins/Unity/Session/LogindServer.cpp (+10/-0)
tests/plugins/Unity/Session/LogindServer.h (+5/-0)
tests/plugins/Unity/Session/interfaces.xml (+12/-0)
tests/plugins/Unity/Session/sessionbackendtest.cpp (+95/-3)
To merge this branch: bzr merge lp:~mterry/unity8/gnome-session-quit
Reviewer Review Type Date Requested Status
Albert Astals Cid (community) Approve
Unity8 CI Bot continuous-integration Approve
Review via email: mp+319992@code.launchpad.net

Commit message

Support GNOME-style logout DBus API (making the Logout, Reboot, and Shutdown launcher commands work)

Description of the change

As noted in bug 1673229, the launcher items "Logout", "Shutdown", and "Reboot" don't do anything in unity8. They are holdovers from GNOME, making calls to the org.gnome.SessionManager interface.

Despite being old-world commands, it would still be nice if we supported them (and other bits of code in classic Ubuntu might try similar calls to the API). Unity7 supports them. And we support the similar (older?) org.gnome.SessionManager.EndSessionDialog interface. So this is a small change for us.

You can test by logging into deb-based unity8 and running those commands from the launcher. There's still a momentary, jarring splash window created for the command. But that's a separate issue.

To post a comment you must log in.
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
lp:~mterry/unity8/gnome-session-quit updated
2870. By Michael Terry

Drop extra whitespace

Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

PASSED: Continuous integration, rev:2870
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/3417/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/4504
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=qmluitests.sh/2708
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=zesty,testname=qmluitests.sh/2708
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/4532
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/4359
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/4359/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=zesty/4359
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=zesty/4359/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/4359
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/4359/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=zesty/4359
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=zesty/4359/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/4359
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/4359/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=zesty/4359
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=zesty/4359/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/3417/rebuild

review: Approve (continuous-integration)
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

PASSED: Continuous integration, rev:2870
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/3422/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/4514
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=qmluitests.sh/2713
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=zesty,testname=qmluitests.sh/2713
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/4542
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/4368
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/4368/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=zesty/4368
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=zesty/4368/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/4368
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/4368/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=zesty/4368
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=zesty/4368/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/4368
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/4368/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=zesty/4368
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=zesty/4368/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/3422/rebuild

review: Approve (continuous-integration)
Revision history for this message
Albert Astals Cid (aacid) wrote :

 * Did you perform an exploratory manual test run of the code change and any related functionality?
Yes

 * Did CI run pass? If not, please explain why.
Yes

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'plugins/Unity/Session/dbusunitysessionservice.cpp'
2--- plugins/Unity/Session/dbusunitysessionservice.cpp 2016-12-19 19:55:07 +0000
3+++ plugins/Unity/Session/dbusunitysessionservice.cpp 2017-03-16 14:04:06 +0000
4@@ -468,11 +468,56 @@
5
6
7 DBusGnomeSessionManagerWrapper::DBusGnomeSessionManagerWrapper()
8+ : UnityDBusObject(QStringLiteral("/org/gnome/SessionManager"), QStringLiteral("org.gnome.SessionManager"))
9+{
10+}
11+
12+void DBusGnomeSessionManagerWrapper::Logout(quint32 mode)
13+{
14+ auto call = QStringLiteral("RequestLogout");
15+
16+ // These modes are documented as bitwise flags, not an enum, even though
17+ // they only ever seem to be used as enums.
18+
19+ if (mode & 1) // without dialog
20+ call = QStringLiteral("Logout");
21+ if (mode & 2) // without dialog, ignoring inhibitors (which we don't have)
22+ call = QStringLiteral("Logout");
23+
24+ performAsyncUnityCall(call);
25+}
26+
27+void DBusGnomeSessionManagerWrapper::Reboot()
28+{
29+ // GNOME's Reboot means with dialog (they use Request differently than us).
30+ performAsyncUnityCall(QStringLiteral("RequestReboot"));
31+}
32+
33+void DBusGnomeSessionManagerWrapper::RequestReboot()
34+{
35+ // GNOME's RequestReboot means no dialog (they use Request differently than us).
36+ performAsyncUnityCall(QStringLiteral("Reboot"));
37+}
38+
39+void DBusGnomeSessionManagerWrapper::RequestShutdown()
40+{
41+ // GNOME's RequestShutdown means no dialog (they use Request differently than us).
42+ performAsyncUnityCall(QStringLiteral("Shutdown"));
43+}
44+
45+void DBusGnomeSessionManagerWrapper::Shutdown()
46+{
47+ // GNOME's Shutdown means with dialog (they use Request differently than us).
48+ performAsyncUnityCall(QStringLiteral("RequestShutdown"));
49+}
50+
51+
52+DBusGnomeSessionManagerDialogWrapper::DBusGnomeSessionManagerDialogWrapper()
53 : UnityDBusObject(QStringLiteral("/org/gnome/SessionManager/EndSessionDialog"), QStringLiteral("com.canonical.Unity"))
54 {
55 }
56
57-void DBusGnomeSessionManagerWrapper::Open(const unsigned type, const unsigned arg_1, const unsigned max_wait, const QList<QDBusObjectPath> &inhibitors)
58+void DBusGnomeSessionManagerDialogWrapper::Open(const unsigned type, const unsigned arg_1, const unsigned max_wait, const QList<QDBusObjectPath> &inhibitors)
59 {
60 Q_UNUSED(arg_1);
61 Q_UNUSED(max_wait);
62
63=== modified file 'plugins/Unity/Session/dbusunitysessionservice.h'
64--- plugins/Unity/Session/dbusunitysessionservice.h 2016-12-19 19:55:07 +0000
65+++ plugins/Unity/Session/dbusunitysessionservice.h 2017-03-16 14:04:06 +0000
66@@ -270,17 +270,31 @@
67 class DBusGnomeSessionManagerWrapper : public UnityDBusObject
68 {
69 Q_OBJECT
70- Q_CLASSINFO("D-Bus Interface", "org.gnome.SessionManager.EndSessionDialog")
71+ Q_CLASSINFO("D-Bus Interface", "org.gnome.SessionManager")
72
73 public:
74 DBusGnomeSessionManagerWrapper();
75 ~DBusGnomeSessionManagerWrapper() = default;
76
77 public Q_SLOTS:
78+ Q_SCRIPTABLE void Logout(quint32 mode);
79+ Q_SCRIPTABLE void Reboot();
80+ Q_SCRIPTABLE void RequestReboot();
81+ Q_SCRIPTABLE void RequestShutdown();
82+ Q_SCRIPTABLE void Shutdown();
83+};
84+
85+class DBusGnomeSessionManagerDialogWrapper : public UnityDBusObject
86+{
87+ Q_OBJECT
88+ Q_CLASSINFO("D-Bus Interface", "org.gnome.SessionManager.EndSessionDialog")
89+
90+public:
91+ DBusGnomeSessionManagerDialogWrapper();
92+ ~DBusGnomeSessionManagerDialogWrapper() = default;
93+
94+public Q_SLOTS:
95 Q_SCRIPTABLE void Open(const unsigned int type, const unsigned int arg_1, const unsigned int max_wait, const QList<QDBusObjectPath> &inhibitors);
96-
97-private:
98- void performAsyncCall(const QString &method);
99 };
100
101 class DBusGnomeScreensaverWrapper: public UnityDBusObject
102
103=== modified file 'tests/plugins/Unity/Session/LogindServer.cpp'
104--- tests/plugins/Unity/Session/LogindServer.cpp 2016-06-22 13:38:16 +0000
105+++ tests/plugins/Unity/Session/LogindServer.cpp 2017-03-16 14:04:06 +0000
106@@ -27,6 +27,16 @@
107 return QDBusObjectPath("/logindsession");
108 }
109
110+void LogindServer::Reboot(bool interactive)
111+{
112+ Q_EMIT RebootCalled(interactive);
113+}
114+
115+void LogindServer::PowerOff(bool interactive)
116+{
117+ Q_EMIT PowerOffCalled(interactive);
118+}
119+
120 void LogindServer::MockEmitUnlock()
121 {
122 Q_EMIT Unlock();
123
124=== modified file 'tests/plugins/Unity/Session/LogindServer.h'
125--- tests/plugins/Unity/Session/LogindServer.h 2016-06-22 13:38:16 +0000
126+++ tests/plugins/Unity/Session/LogindServer.h 2017-03-16 14:04:06 +0000
127@@ -31,6 +31,8 @@
128
129 public Q_SLOTS:
130 QDBusObjectPath GetSessionByPID(quint32 pid);
131+ void Reboot(bool interactive);
132+ void PowerOff(bool interactive);
133
134 void MockEmitUnlock(); // only in mock
135
136@@ -38,6 +40,9 @@
137 void Lock();
138 void Unlock();
139 void PrepareForSleep();
140+
141+ void RebootCalled(bool interactive); // only in mock
142+ void PowerOffCalled(bool interactive); // only in mock
143 };
144
145 #endif
146
147=== modified file 'tests/plugins/Unity/Session/interfaces.xml'
148--- tests/plugins/Unity/Session/interfaces.xml 2016-06-22 13:38:16 +0000
149+++ tests/plugins/Unity/Session/interfaces.xml 2017-03-16 14:04:06 +0000
150@@ -7,6 +7,18 @@
151 <arg name="pid" type="u" direction="in" />
152 <arg name="session" type="o" direction="out" />
153 </method>
154+ <method name="Reboot">
155+ <arg name="interactive" type="b" direction="in" />
156+ </method>
157+ <method name="PowerOff">
158+ <arg name="interactive" type="b" direction="in" />
159+ </method>
160+ <signal name="RebootCalled">
161+ <arg name="interactive" type="b" direction="out" />
162+ </signal>
163+ <signal name="PowerOffCalled">
164+ <arg name="interactive" type="b" direction="out" />
165+ </signal>
166 <signal name="PrepareForSleep" />
167 </interface>
168 <interface name="org.freedesktop.login1.Session">
169
170=== modified file 'tests/plugins/Unity/Session/sessionbackendtest.cpp'
171--- tests/plugins/Unity/Session/sessionbackendtest.cpp 2016-12-19 19:55:07 +0000
172+++ tests/plugins/Unity/Session/sessionbackendtest.cpp 2017-03-16 14:04:06 +0000
173@@ -81,7 +81,99 @@
174 QTRY_COMPARE(spy.count(), 1);
175 }
176
177- void testGnomeSessionWrapper_data() {
178+ void testGnomeSessionWrapperWithoutConfirmation_data() {
179+ QTest::addColumn<QString>("method");
180+ QTest::addColumn<QString>("signal");
181+
182+ QTest::newRow("Reboot") << "RequestReboot" << SIGNAL(RebootCalled(bool));
183+ QTest::newRow("Shutdown") << "RequestShutdown" << SIGNAL(PowerOffCalled(bool));
184+ }
185+
186+ void testGnomeSessionWrapperWithoutConfirmation() {
187+ QFETCH(QString, method);
188+ QFETCH(QString, signal);
189+
190+ DBusUnitySessionService dbusUnitySessionService;
191+ DBusGnomeSessionManagerWrapper dbusGnomeSessionManagerWrapper;
192+ QCoreApplication::processEvents(); // to let the services register on DBus
193+
194+ QDBusInterface login1Interface("org.freedesktop.login1",
195+ "/logindsession",
196+ "org.freedesktop.login1.Manager");
197+ QSignalSpy spy(&login1Interface, signal.toUtf8().data());
198+
199+ QDBusInterface dbusGnomeSessionWrapper("org.gnome.SessionManager",
200+ "/org/gnome/SessionManager",
201+ "org.gnome.SessionManager",
202+ QDBusConnection::sessionBus());
203+ QVERIFY(dbusGnomeSessionWrapper.isValid());
204+
205+ QDBusReply<void> reply = dbusGnomeSessionWrapper.call(method);
206+ QVERIFY(reply.isValid());
207+ QTRY_COMPARE(spy.count(), 1);
208+ }
209+
210+ void testGnomeSessionWrapperWithConfirmation_data() {
211+ QTest::addColumn<QString>("method");
212+ QTest::addColumn<QString>("signal");
213+
214+ QTest::newRow("Reboot") << "Reboot" << SIGNAL(RebootRequested(bool));
215+ QTest::newRow("Shutdown") << "Shutdown" << SIGNAL(ShutdownRequested(bool));
216+ }
217+
218+ void testGnomeSessionWrapperWithConfirmation() {
219+ QFETCH(QString, method);
220+ QFETCH(QString, signal);
221+
222+ DBusUnitySessionService dbusUnitySessionService;
223+ DBusGnomeSessionManagerWrapper dbusGnomeSessionManagerWrapper;
224+ QCoreApplication::processEvents(); // to let the services register on DBus
225+
226+ QSignalSpy spy(&dbusUnitySessionService, signal.toUtf8().data());
227+
228+ QDBusInterface dbusGnomeSessionWrapper("org.gnome.SessionManager",
229+ "/org/gnome/SessionManager",
230+ "org.gnome.SessionManager",
231+ QDBusConnection::sessionBus());
232+ QVERIFY(dbusGnomeSessionWrapper.isValid());
233+
234+ QDBusReply<void> reply = dbusGnomeSessionWrapper.call(method);
235+ QVERIFY(reply.isValid());
236+ QCOMPARE(spy.count(), 1);
237+ }
238+
239+ void testGnomeSessionWrapperLogout_data() {
240+ QTest::addColumn<int>("mode");
241+ QTest::addColumn<QString>("signal");
242+
243+ QTest::newRow("Logout") << 0 << SIGNAL(LogoutRequested(bool));
244+ QTest::newRow("LogoutNoDialog") << 1 << SIGNAL(LogoutReady());
245+ QTest::newRow("LogoutNoInhibits") << 2 << SIGNAL(LogoutReady());
246+ QTest::newRow("LogoutNoDialogNoInhibits") << 3 << SIGNAL(LogoutReady());
247+ }
248+
249+ void testGnomeSessionWrapperLogout() {
250+ QFETCH(int, mode);
251+ QFETCH(QString, signal);
252+
253+ DBusUnitySessionService dbusUnitySessionService;
254+ DBusGnomeSessionManagerWrapper dbusGnomeSessionManagerWrapper;
255+ QCoreApplication::processEvents(); // to let the services register on DBus
256+
257+ QSignalSpy spy(&dbusUnitySessionService, signal.toUtf8().data());
258+
259+ QDBusInterface dbusGnomeSessionWrapper("org.gnome.SessionManager",
260+ "/org/gnome/SessionManager",
261+ "org.gnome.SessionManager",
262+ QDBusConnection::sessionBus());
263+ QVERIFY(dbusGnomeSessionWrapper.isValid());
264+
265+ QDBusReply<void> reply = dbusGnomeSessionWrapper.call("Logout", (quint32)mode);
266+ QVERIFY(reply.isValid());
267+ QCOMPARE(spy.count(), 1);
268+ }
269+
270+ void testGnomeSessionDialogWrapper_data() {
271 QTest::addColumn<uint>("method");
272 QTest::addColumn<QString>("signal");
273
274@@ -90,7 +182,7 @@
275 QTest::newRow("Reboot") << (uint)Action::REBOOT << "RebootRequested(bool)";
276 }
277
278- void testGnomeSessionWrapper() {
279+ void testGnomeSessionDialogWrapper() {
280 QFETCH(uint, method);
281 QFETCH(QString, signal);
282
283@@ -102,7 +194,7 @@
284 // .. because QSignalSpy checks the signal signature like this: "if (((aSignal[0] - '0') & 0x03) != QSIGNAL_CODE)"
285 QSignalSpy spy(&dbusUnitySessionService, qPrintable(signal.prepend(QSIGNAL_CODE)));
286
287- DBusGnomeSessionManagerWrapper dbusGnomeSessionManagerWrapper;
288+ DBusGnomeSessionManagerDialogWrapper dbusGnomeSessionManagerDialogWrapper;
289 QCoreApplication::processEvents(); // to let the service register on DBus
290
291 QDBusInterface dbusGnomeSessionWrapper("com.canonical.Unity",

Subscribers

People subscribed via source and target branches