Merge lp:~3v1n0/unity/gnome-keygrabber-refactor into lp:unity

Proposed by Marco Trevisan (Treviño)
Status: Merged
Approved by: Marco Trevisan (Treviño)
Approved revision: no longer in the source branch.
Merged at revision: 4018
Proposed branch: lp:~3v1n0/unity/gnome-keygrabber-refactor
Merge into: lp:unity
Diff against target: 1492 lines (+537/-310)
26 files modified
CMakeLists.txt (+2/-2)
UnityCore/CMakeLists.txt (+2/-0)
UnityCore/GLibDBusNameWatcher.cpp (+44/-0)
UnityCore/GLibDBusNameWatcher.h (+54/-0)
UnityCore/GLibDBusProxy.cpp (+7/-3)
UnityCore/GLibDBusServer.cpp (+27/-16)
UnityCore/GLibDBusServer.h (+7/-5)
panel/StandalonePanel.cpp (+4/-6)
tests/CMakeLists.txt (+1/-1)
tests/autopilot/unity/tests/test_gnome_key_grabber.py (+9/-17)
tests/mock_key_grabber.h (+3/-2)
tests/test_glib_dbus_proxy.cpp (+44/-31)
tests/test_gnome_session_manager.cpp (+1/-1)
tests/test_icon_loader.cpp (+8/-8)
tests/test_main_dbus.cpp (+17/-19)
tests/test_result_renderer.cpp (+1/-1)
tests/test_service_panel.cpp (+8/-0)
tests/test_showdesktop_handler.cpp (+2/-1)
tests/test_utils.h (+10/-0)
tests/test_xdnd_start_stop_notifier_imp.cpp (+2/-2)
unity-shared/GnomeKeyGrabber.cpp (+219/-143)
unity-shared/GnomeKeyGrabber.h (+5/-3)
unity-shared/GnomeKeyGrabberImpl.h (+43/-32)
unity-shared/KeyGrabber.h (+4/-2)
unity-shared/MenuManager.cpp (+9/-9)
unity-standalone/StandaloneUnity.cpp (+4/-6)
To merge this branch: bzr merge lp:~3v1n0/unity/gnome-keygrabber-refactor
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Needs Fixing
Andrea Azzarone (community) Approve
Review via email: mp+272858@code.launchpad.net

Commit message

GnomeKeyGrabber: Don't allow an action to be grabbed multiple times

And always return the same action id for a specific key binding.

Description of the change

1) Simplify Gnome key grabber actions allocation
2) Don't grab an action multiple times (at compiz level)
3) Only emit signals to the component that has requested the grab (and remove these on vanished)

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Andrea Azzarone (azzar1) wrote :

LGTM. Please next time avoid to changes thing that don't need to be changed (LoaderIcon...).

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2015-03-19 15:03:58 +0000
3+++ CMakeLists.txt 2015-10-01 03:52:29 +0000
4@@ -15,8 +15,8 @@
5 set (UNITY_API_VERSION "6.0")
6 set (UNITY_COMPONENTS_VERSION "6")
7
8-set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGNOME_DESKTOP_USE_UNSTABLE_API -std=c++0x -fno-permissive")
9-set (CMAKE_CXX_FLAGS_DEBUG "-g3")
10+set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGNOME_DESKTOP_USE_UNSTABLE_API -std=c++11 -fno-permissive")
11+set (CMAKE_CXX_FLAGS_DEBUG "-g3 -DUNITY_DEBUG_BUILD")
12 set (CMAKE_CXX_FLAGS_RELEASE "")
13
14 option(
15
16=== modified file 'UnityCore/CMakeLists.txt'
17--- UnityCore/CMakeLists.txt 2014-12-19 16:37:49 +0000
18+++ UnityCore/CMakeLists.txt 2015-10-01 03:52:29 +0000
19@@ -25,6 +25,7 @@
20 Filter.h
21 Filters.h
22 GenericPreview.h
23+ GLibDBusNameWatcher.h
24 GLibDBusProxy.h
25 GLibDBusServer.h
26 GLibSignal.h
27@@ -80,6 +81,7 @@
28 Filter.cpp
29 Filters.cpp
30 GenericPreview.cpp
31+ GLibDBusNameWatcher.cpp
32 GLibDBusProxy.cpp
33 GLibDBusServer.cpp
34 GLibSignal.cpp
35
36=== added file 'UnityCore/GLibDBusNameWatcher.cpp'
37--- UnityCore/GLibDBusNameWatcher.cpp 1970-01-01 00:00:00 +0000
38+++ UnityCore/GLibDBusNameWatcher.cpp 2015-10-01 03:52:29 +0000
39@@ -0,0 +1,44 @@
40+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
41+/*
42+ * Copyright (C) 2015 Canonical Ltd
43+ *
44+ * This program is free software: you can redistribute it and/or modify
45+ * it under the terms of the GNU General Public License version 3 as
46+ * published by the Free Software Foundation.
47+ *
48+ * This program is distributed in the hope that it will be useful,
49+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
50+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
51+ * GNU General Public License for more details.
52+ *
53+ * You should have received a copy of the GNU General Public License
54+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
55+ *
56+ * Authored by: Marco Trevisan (Treviño) <marco.trevisan@canonical.com>
57+ */
58+
59+#include "GLibDBusNameWatcher.h"
60+#include "GLibWrapper.h"
61+
62+namespace unity
63+{
64+namespace glib
65+{
66+
67+DBusNameWatcher::DBusNameWatcher(std::string const& name, GBusType bus_type, GBusNameWatcherFlags flags)
68+ : watcher_id_(g_bus_watch_name(bus_type, name.c_str(), flags,
69+ [] (GDBusConnection *connection, const gchar *name, const gchar *name_owner, gpointer self) {
70+ static_cast<DBusNameWatcher*>(self)->appeared.emit(gchar_to_string(name), gchar_to_string(name_owner));
71+ },
72+ [] (GDBusConnection *connection, const gchar *name, gpointer self) {
73+ static_cast<DBusNameWatcher*>(self)->vanished.emit(gchar_to_string(name));
74+ }, this, nullptr))
75+{}
76+
77+DBusNameWatcher::~DBusNameWatcher()
78+{
79+ g_bus_unwatch_name(watcher_id_);
80+}
81+
82+} // namespace glib
83+} // namespace unity
84
85=== added file 'UnityCore/GLibDBusNameWatcher.h'
86--- UnityCore/GLibDBusNameWatcher.h 1970-01-01 00:00:00 +0000
87+++ UnityCore/GLibDBusNameWatcher.h 2015-10-01 03:52:29 +0000
88@@ -0,0 +1,54 @@
89+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
90+/*
91+ * Copyright (C) 2015 Canonical Ltd
92+ *
93+ * This program is free software: you can redistribute it and/or modify
94+ * it under the terms of the GNU General Public License version 3 as
95+ * published by the Free Software Foundation.
96+ *
97+ * This program is distributed in the hope that it will be useful,
98+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
99+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
100+ * GNU General Public License for more details.
101+ *
102+ * You should have received a copy of the GNU General Public License
103+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
104+ *
105+ * Authored by: Marco Trevisan (Treviño) <marco.trevisan@canonical.com>
106+ */
107+
108+#ifndef UNITY_GLIB_DBUS_NAME_WATCHER_H
109+#define UNITY_GLIB_DBUS_NAME_WATCHER_H
110+
111+#include <gio/gio.h>
112+#include <memory>
113+#include <sigc++/signal.h>
114+
115+namespace unity
116+{
117+namespace glib
118+{
119+
120+class DBusNameWatcher
121+{
122+public:
123+ typedef std::shared_ptr<DBusNameWatcher> Ptr;
124+
125+ DBusNameWatcher(std::string const& name, GBusType bus_type = G_BUS_TYPE_SESSION, GBusNameWatcherFlags flags = G_BUS_NAME_WATCHER_FLAGS_NONE);
126+ virtual ~DBusNameWatcher();
127+
128+ sigc::signal<void, std::string const& /* name*/, std::string const& /* name owner*/> appeared;
129+ sigc::signal<void, std::string const& /* name */> vanished;
130+
131+private:
132+ // not copyable class
133+ DBusNameWatcher(DBusNameWatcher const&) = delete;
134+ DBusNameWatcher& operator=(DBusNameWatcher const&) = delete;
135+
136+ uint32_t watcher_id_;
137+};
138+
139+} // namespace glib
140+} // namespace unity
141+
142+#endif //UNITY_GLIB_DBUS_NAME_WATCHER_H
143
144=== modified file 'UnityCore/GLibDBusProxy.cpp'
145--- UnityCore/GLibDBusProxy.cpp 2015-05-19 18:21:31 +0000
146+++ UnityCore/GLibDBusProxy.cpp 2015-10-01 03:52:29 +0000
147@@ -344,7 +344,8 @@
148 // wait for the signal
149 *con = proxy_acquired.connect([con, canc, timeout, callback] ()
150 {
151- if (!g_cancellable_is_cancelled(canc)) callback(glib::Error());
152+ if (!g_cancellable_is_cancelled(canc))
153+ callback(glib::Error());
154
155 timeout->Remove();
156 con->disconnect();
157@@ -390,12 +391,15 @@
158 if (!proxy_)
159 {
160 glib::Variant sinked_parameters(parameters);
161- glib::Object<GCancellable>canc(target_canc, glib::AddRef());
162+ glib::Object<GCancellable> canc(target_canc, glib::AddRef());
163+
164 WaitForProxy(canc, timeout_msec, [this, method_name, sinked_parameters, callback, canc, flags, timeout_msec] (glib::Error const& err)
165 {
166 if (err)
167 {
168- callback(glib::Variant(), err);
169+ if (callback)
170+ callback(glib::Variant(), err);
171+
172 LOG_WARNING(logger) << "Cannot call method " << method_name
173 << ": " << err;
174 }
175
176=== modified file 'UnityCore/GLibDBusServer.cpp'
177--- UnityCore/GLibDBusServer.cpp 2015-02-03 09:46:48 +0000
178+++ UnityCore/GLibDBusServer.cpp 2015-10-01 03:52:29 +0000
179@@ -87,7 +87,7 @@
180
181 if (self->method_cb_)
182 {
183- ret = self->method_cb_(method_name ? method_name : "", parameters);
184+ ret = self->method_cb_(gchar_to_string(method_name), parameters, gchar_to_string(sender), gchar_to_string(object_path));
185
186 LOG_INFO(logger_o) << "Called method: '" << method_name << " " << parameters
187 << "' on object '" << object_path << "' with interface '"
188@@ -295,13 +295,14 @@
189
190 void EmitGenericSignal(glib::Object<GDBusConnection> const& conn, std::string const& path,
191 std::string const& interface, std::string const& signal,
192- GVariant* parameters = nullptr)
193+ GVariant* parameters = nullptr, std::string const& dest = "")
194 {
195 LOG_INFO(logger_o) << "Emitting signal '" << signal << "'" << " for the interface "
196 << "'" << interface << "' on object path '" << path << "'";
197
198 glib::Error error;
199- g_dbus_connection_emit_signal(conn, nullptr, path.c_str(), interface.c_str(),
200+ g_dbus_connection_emit_signal(conn, dest.empty() ? nullptr : dest.c_str(),
201+ path.c_str(), interface.c_str(),
202 signal.c_str(), parameters, &error);
203
204 if (error)
205@@ -312,7 +313,7 @@
206 }
207 }
208
209- void EmitSignal(std::string const& signal, GVariant* parameters, std::string const& path)
210+ void EmitSignal(std::string const& signal, GVariant* parameters, std::string const& dest, std::string const& path)
211 {
212 glib::Variant reffed_params(parameters);
213
214@@ -333,7 +334,7 @@
215 return;
216 }
217
218- EmitGenericSignal(conn_it->second, path, InterfaceName(), signal, parameters);
219+ EmitGenericSignal(conn_it->second, path, InterfaceName(), signal, parameters, dest);
220 }
221 else
222 {
223@@ -343,7 +344,7 @@
224 auto const& obj_path = pair.first;
225 auto const& conn = pair.second;
226
227- EmitGenericSignal(conn, obj_path, InterfaceName(), signal, params);
228+ EmitGenericSignal(conn, obj_path, InterfaceName(), signal, params, dest);
229 }
230 }
231 }
232@@ -401,7 +402,7 @@
233 }
234
235 DBusObject* object_;
236- MethodCallback method_cb_;
237+ MethodCallbackFull method_cb_;
238 PropertyGetterCallback property_get_cb_;
239 PropertySetterCallback property_set_cb_;
240
241@@ -420,6 +421,18 @@
242
243 void DBusObject::SetMethodsCallsHandler(MethodCallback const& func)
244 {
245+ impl_->method_cb_ = nullptr;
246+
247+ if (func)
248+ {
249+ impl_->method_cb_ = [func] (std::string const& method, GVariant* parameters, std::string const&, std::string const&) {
250+ return func(method, parameters);
251+ };
252+ }
253+}
254+
255+void DBusObject::SetMethodsCallsHandlerFull(MethodCallbackFull const& func)
256+{
257 impl_->method_cb_ = func;
258 }
259
260@@ -448,9 +461,9 @@
261 impl_->UnRegister(path);
262 }
263
264-void DBusObject::EmitSignal(std::string const& signal, GVariant* parameters, std::string const& path)
265+void DBusObject::EmitSignal(std::string const& signal, GVariant* parameters, std::string const& dest, std::string const& path)
266 {
267- impl_->EmitSignal(signal, parameters, path);
268+ impl_->EmitSignal(signal, parameters, dest, path);
269 }
270
271 void DBusObject::EmitPropertyChanged(std::string const& property, std::string const& path)
272@@ -648,12 +661,10 @@
273 return DBusObject::Ptr();
274 }
275
276- void EmitSignal(std::string const& interface, std::string const& signal, GVariant* parameters)
277+ void EmitSignal(std::string const& interface, std::string const& signal, GVariant* parameters, std::string const& dest)
278 {
279- auto const& obj = GetObject(interface);
280-
281- if (obj)
282- obj->EmitSignal(signal, parameters);
283+ if (DBusObject::Ptr const& obj = GetObject(interface))
284+ obj->EmitSignal(signal, parameters, dest);
285 }
286
287 DBusServer* server_;
288@@ -735,9 +746,9 @@
289 return impl_->GetObject(interface);
290 }
291
292-void DBusServer::EmitSignal(std::string const& interface, std::string const& signal, GVariant* parameters)
293+void DBusServer::EmitSignal(std::string const& interface, std::string const& signal, GVariant* parameters, std::string const& dest)
294 {
295- impl_->EmitSignal(interface, signal, parameters);
296+ impl_->EmitSignal(interface, signal, parameters, dest);
297 }
298
299 } // namespace glib
300
301=== modified file 'UnityCore/GLibDBusServer.h'
302--- UnityCore/GLibDBusServer.h 2014-04-09 13:19:33 +0000
303+++ UnityCore/GLibDBusServer.h 2015-10-01 03:52:29 +0000
304@@ -40,11 +40,13 @@
305 DBusObject(std::string const& introspection_xml, std::string const& interface_name);
306 virtual ~DBusObject();
307
308- typedef std::function<GVariant*(std::string const&, GVariant*)> MethodCallback;
309- typedef std::function<GVariant*(std::string const&)> PropertyGetterCallback;
310- typedef std::function<bool(std::string const&, GVariant*)> PropertySetterCallback;
311+ typedef std::function<GVariant*(std::string const& /*method*/, GVariant* /*parameters*/)> MethodCallback;
312+ typedef std::function<GVariant*(std::string const& /*method*/, GVariant* /*parameters*/, std::string const& /*sender*/, std::string const& /*object_path*/)> MethodCallbackFull;
313+ typedef std::function<GVariant*(std::string const& /*name*/)> PropertyGetterCallback;
314+ typedef std::function<bool(std::string const& /*name*/, GVariant* /*value*/)> PropertySetterCallback;
315
316 void SetMethodsCallsHandler(MethodCallback const&);
317+ void SetMethodsCallsHandlerFull(MethodCallbackFull const&);
318 void SetPropertyGetter(PropertyGetterCallback const&);
319 void SetPropertySetter(PropertySetterCallback const&);
320
321@@ -53,7 +55,7 @@
322 bool Register(glib::Object<GDBusConnection> const&, std::string const& path);
323 void UnRegister(std::string const& path = "");
324
325- void EmitSignal(std::string const& signal, GVariant* parameters = nullptr, std::string const& path = "");
326+ void EmitSignal(std::string const& signal, GVariant* parameters = nullptr, std::string const& dest = "", std::string const& path = "");
327 void EmitPropertyChanged(std::string const& property, std::string const& path = "");
328
329 sigc::signal<void, std::string const&> registered;
330@@ -91,7 +93,7 @@
331 std::list<DBusObject::Ptr> GetObjects() const;
332 DBusObject::Ptr GetObject(std::string const& interface) const;
333
334- void EmitSignal(std::string const& interface, std::string const& signal, GVariant* parameters = nullptr);
335+ void EmitSignal(std::string const& interface, std::string const& signal, GVariant* parameters = nullptr, std::string const& dest = "");
336
337 bool IsConnected() const;
338 std::string const& Name() const;
339
340=== modified file 'panel/StandalonePanel.cpp'
341--- panel/StandalonePanel.cpp 2014-02-17 20:15:02 +0000
342+++ panel/StandalonePanel.cpp 2015-10-01 03:52:29 +0000
343@@ -63,12 +63,10 @@
344
345 struct MockKeyGrabber : key::Grabber
346 {
347- CompAction::Vector& GetActions() { return actions_; }
348- void AddAction(CompAction const&) {}
349- void RemoveAction(CompAction const&) {}
350-
351- private:
352- CompAction::Vector actions_;
353+ CompAction::Vector& GetActions() override { return noActions(); }
354+ uint32_t AddAction(CompAction const&) override { return 0; };
355+ bool RemoveAction(CompAction const&) override { return false; };
356+ bool RemoveAction(uint32_t id) override { return false; };
357 };
358
359 void Init()
360
361=== modified file 'tests/CMakeLists.txt'
362--- tests/CMakeLists.txt 2015-09-08 02:19:56 +0000
363+++ tests/CMakeLists.txt 2015-10-01 03:52:29 +0000
364@@ -355,7 +355,7 @@
365 endif (ENABLE_X_SUPPORT)
366 set (GTEST_TEST_COMMAND_XLESS ./test-gtest-xless --gtest_output=xml:./test-gtest-xless.xml)
367 set (GTEST_TEST_COMMAND_SLOW ./test-gtest-slow --gtest_output=xml:./test-gtest-slow.xml)
368-set (GTEST_TEST_COMMAND_DBUS dbus-test-runner --max-wait=300 --task ./test-gtest-service --task-name test-service --task=./test-gtest-dbus --task-name=test-dbus --wait-for=com.canonical.Unity.Test.Scope --parameter=--gtest_output=xml:./test-gtest-dbus.xml --parameter=--gtest_filter=-TestCategoriesChanging*)
369+set (GTEST_TEST_COMMAND_DBUS dbus-test-runner --max-wait=300 --task ./test-gtest-service --task-name test-service --task=./test-gtest-dbus --task-name=test-gtest-dbus --wait-for=com.canonical.Unity.Test --parameter=--gtest_output=xml:./test-gtest-dbus.xml --parameter=--gtest_filter=-TestCategoriesChanging*)
370
371 set (TEST_COMMAND_XLESS
372 ${GTEST_TEST_COMMAND_XLESS}
373
374=== modified file 'tests/autopilot/unity/tests/test_gnome_key_grabber.py'
375--- tests/autopilot/unity/tests/test_gnome_key_grabber.py 2015-03-24 13:58:12 +0000
376+++ tests/autopilot/unity/tests/test_gnome_key_grabber.py 2015-10-01 03:52:29 +0000
377@@ -154,20 +154,12 @@
378
379 self.addCleanup(clean_up_test_grab_same_accelerator)
380
381- for accelerator in accelerators:
382- # Check that accelerator works
383- self.assertTrue(self.press_accelerator(accelerator))
384-
385- # Remove accelerator
386- log.info('ungrabbing %s' % accelerator)
387- self.assertTrue(self.interface.UngrabAccelerator(accelerator.action))
388-
389- # This accelerator cannot activate any more
390- self.activatable.remove(accelerator.action)
391-
392- # Add them all again for one final check
393- for accelerator in accelerators:
394- self.activatable.add(accelerator.action)
395-
396- # Check that signal was not emitted
397- self.assertFalse(self.press_accelerator(accelerators[0]))
398+ # Check that accelerator works
399+ self.assertTrue(self.press_accelerator(accelerator))
400+
401+ # Remove accelerator
402+ log.info('ungrabbing %s' % accelerator)
403+ self.assertTrue(self.interface.UngrabAccelerator(accelerator.action))
404+
405+ for accelerator in accelerators[1:]:
406+ self.assertFalse(self.press_accelerator(accelerator))
407
408=== modified file 'tests/mock_key_grabber.h'
409--- tests/mock_key_grabber.h 2014-02-12 07:13:01 +0000
410+++ tests/mock_key_grabber.h 2015-10-01 03:52:29 +0000
411@@ -39,8 +39,9 @@
412 }
413
414 MOCK_METHOD0(GetActions, CompAction::Vector&());
415- MOCK_METHOD1(AddAction, void(CompAction const&));
416- MOCK_METHOD1(RemoveAction, void(CompAction const&));
417+ MOCK_METHOD1(AddAction, uint32_t(CompAction const&));
418+ MOCK_METHOD1(RemoveAction, bool(CompAction const&));
419+ MOCK_METHOD1(RemoveAction, bool(uint32_t));
420
421 CompAction::Vector actions_;
422 };
423
424=== modified file 'tests/test_glib_dbus_proxy.cpp'
425--- tests/test_glib_dbus_proxy.cpp 2013-04-08 14:18:46 +0000
426+++ tests/test_glib_dbus_proxy.cpp 2015-10-01 03:52:29 +0000
427@@ -88,73 +88,85 @@
428
429 Utils::WaitUntilMSec(got_result_return);
430 Utils::WaitUntilMSec(got_signal_return);
431-
432+
433 EXPECT_EQ(returned_result, expected_return);
434 EXPECT_EQ(returned_signal, expected_return);
435 }
436
437-TEST_F(TestGDBusProxy, TestCancelling)
438-{
439- std::string call_return;
440- // method callback
441- auto method_connection = [&](GVariant *variant)
442- {
443- if (variant != nullptr)
444- {
445- call_return = g_variant_get_string(g_variant_get_child_value(variant, 0), NULL);
446- }
447-
448+TEST_F(TestGDBusProxy, TestCancellingBeforeConnecting)
449+{
450+ // method callback
451+ auto method_connection = [this](GVariant *variant, glib::Error const& e)
452+ {
453+ got_result_return = true;
454+ };
455+
456+ Utils::WaitUntilMSec(sigc::mem_fun(proxy, &glib::DBusProxy::IsConnected));
457+
458+ glib::Cancellable cancellable;
459+ proxy.CallBegin("TestMethod", g_variant_new("(s)", "TestStringTestString"),
460+ method_connection, cancellable);
461+
462+ cancellable.Cancel();
463+
464+ Utils::WaitPendingEvents();
465+ EXPECT_FALSE(got_result_return);
466+}
467+
468+TEST_F(TestGDBusProxy, TestCancellingAfterConnecting)
469+{
470+ // method callback
471+ auto method_connection = [this](GVariant *variant, glib::Error const& e)
472+ {
473 got_result_return = true;
474 };
475
476 EXPECT_FALSE(proxy.IsConnected()); // we shouldn't be connected yet
477+
478 glib::Cancellable cancellable;
479- // but this has to work eitherway
480- proxy.Call("TestMethod", g_variant_new("(s)", "TestStringTestString"),
481- method_connection, cancellable);
482+ proxy.CallBegin("TestMethod", g_variant_new("(s)", "TestStringTestString"),
483+ method_connection, cancellable);
484
485- // this could mostly cause the next test to fail
486+ Utils::WaitUntilMSec(sigc::mem_fun(proxy, &glib::DBusProxy::IsConnected));
487 cancellable.Cancel();
488+
489+ Utils::WaitPendingEvents();
490 EXPECT_FALSE(got_result_return);
491 }
492
493-TEST_F(TestGDBusProxy, TestAcquiring)
494+TEST_F(TestGDBusProxy, TestMultipleCalls)
495 {
496 const int NUM_REQUESTS = 10;
497 int completed = 0;
498 std::string call_return;
499 // method callback
500- auto method_connection = [&](GVariant* variant, glib::Error const& err)
501+ auto method_connection = [&](GVariant* variant)
502 {
503- if (variant != nullptr)
504- {
505- call_return = g_variant_get_string(g_variant_get_child_value(variant, 0), NULL);
506- }
507-
508 if (++completed >= NUM_REQUESTS) got_result_return = true;
509 };
510
511 EXPECT_FALSE(proxy.IsConnected()); // we shouldn't be connected yet
512 for (int i = 0; i < NUM_REQUESTS; i++)
513- {
514- proxy.CallBegin("TestMethod", g_variant_new("(s)", "TestStringTestString"),
515- method_connection, nullptr);
516- Utils::WaitForTimeoutMSec(150);
517- }
518- Utils::WaitUntilMSec(got_result_return, 2);
519+ proxy.Call("TestMethod", g_variant_new("(s)", "TestStringTestString"), method_connection, nullptr);
520+
521+ Utils::WaitPendingEvents();
522+ Utils::WaitUntilMSec(got_result_return, 150, G_STRLOC);
523+ EXPECT_EQ(completed, NUM_REQUESTS);
524 }
525
526 TEST_F(TestGDBusProxyInvalidService, TestTimeouting)
527 {
528 std::string call_return;
529+ bool error;
530 // method callback
531- auto method_connection = [&](GVariant* variant, glib::Error const& err)
532+ auto method_connection = [&](GVariant* variant, glib::Error const& e)
533 {
534 if (variant != nullptr)
535 {
536 call_return = g_variant_get_string(g_variant_get_child_value(variant, 0), NULL);
537 }
538
539+ error = e;
540 got_result_return = true;
541 };
542
543@@ -168,6 +180,7 @@
544
545 Utils::WaitUntilMSec(got_result_return);
546 EXPECT_EQ(call_return, "");
547+ EXPECT_TRUE(error);
548 }
549
550 TEST_F(TestGDBusProxy, TestMethodCall)
551@@ -190,7 +203,7 @@
552 method_connection);
553
554 Utils::WaitUntilMSec(got_result_return);
555-
556+
557 EXPECT_TRUE(proxy.IsConnected());
558 EXPECT_EQ("TestStringTestString", call_return);
559 }
560
561=== modified file 'tests/test_gnome_session_manager.cpp'
562--- tests/test_gnome_session_manager.cpp 2015-09-08 01:54:55 +0000
563+++ tests/test_gnome_session_manager.cpp 2015-10-01 03:52:29 +0000
564@@ -1090,7 +1090,7 @@
565 EXPECT_TRUE(unlock_emitted);
566 }
567
568-TEST_F(TestGnomeSessionManager, NoLockWhenLockingDisabled)
569+TEST_F(TestGnomeSessionManager, UNSTABLE_TEST(NoLockWhenLockingDisabled))
570 {
571 bool lock_emitted = false;
572 bool screensaver_emitted = false;
573
574=== modified file 'tests/test_icon_loader.cpp'
575--- tests/test_icon_loader.cpp 2014-07-30 00:49:35 +0000
576+++ tests/test_icon_loader.cpp 2015-10-01 03:52:29 +0000
577@@ -53,6 +53,7 @@
578
579 void CheckResults(std::vector<LoadResult> const& results)
580 {
581+ Utils::WaitPendingEvents(WAIT_TIMEOUT);
582 Utils::WaitUntilMSec([&results] {
583 bool got_all = true;
584 for (auto const& result : results)
585@@ -101,8 +102,7 @@
586 EXPECT_EQ(&icon_loader, &IconLoader::GetDefault());
587 }
588
589-// FIXME: Disabled due to issues on Jenkins using GLibDBusProxy (lp:1224643)
590-TEST_F(TestIconLoader, DISABLED_TestGetOneIcon)
591+TEST_F(TestIconLoader, UNSTABLE_TEST(TestGetOneIcon))
592 {
593 LoadResult load_result;
594
595@@ -110,13 +110,13 @@
596 &LoadResult::IconLoaded));
597 handles_.push_back(handle);
598
599+ Utils::WaitPendingEvents(WAIT_TIMEOUT);
600 Utils::WaitUntilMSec(load_result.got_callback, WAIT_TIMEOUT);
601 EXPECT_TRUE(load_result.got_callback);
602 EXPECT_TRUE(IsValidPixbuf(load_result.pixbuf));
603 }
604
605-// FIXME: Disabled due to issues on Jenkins using GLibDBusProxy (lp:1224643)
606-TEST_F(TestIconLoader, DISABLED_TestGetAnnotatedIcon)
607+TEST_F(TestIconLoader, UNSTABLE_TEST(TestGetAnnotatedIcon))
608 {
609 LoadResult load_result;
610
611@@ -124,13 +124,13 @@
612 &LoadResult::IconLoaded));
613 handles_.push_back(handle);
614
615+ Utils::WaitPendingEvents(WAIT_TIMEOUT);
616 Utils::WaitUntilMSec(load_result.got_callback, WAIT_TIMEOUT);
617 EXPECT_TRUE(load_result.got_callback);
618 EXPECT_TRUE(IsValidPixbuf(load_result.pixbuf));
619 }
620
621-// FIXME: Disabled due to issues on Jenkins using GLibDBusProxy (lp:1224643)
622-TEST_F(TestIconLoader, DISABLED_TestGetColorizedIcon)
623+TEST_F(TestIconLoader, UNSTABLE_TEST(TestGetColorizedIcon))
624 {
625 LoadResult load_result;
626
627@@ -138,6 +138,7 @@
628 &LoadResult::IconLoaded));
629 handles_.push_back(handle);
630
631+ Utils::WaitPendingEvents(WAIT_TIMEOUT);
632 Utils::WaitUntilMSec(load_result.got_callback, WAIT_TIMEOUT);
633 EXPECT_TRUE(load_result.got_callback);
634 EXPECT_TRUE(IsValidPixbuf(load_result.pixbuf));
635@@ -173,8 +174,7 @@
636 CheckResults(results);
637 }
638
639-// Disabled until we have the new thread safe lp:fontconfig
640-TEST_F(TestIconLoader, DISABLED_TestGetManyIcons)
641+TEST_F(TestIconLoader, TestGetManyIcons)
642 {
643 std::vector<LoadResult> results;
644 int i = 0;
645
646=== modified file 'tests/test_main_dbus.cpp'
647--- tests/test_main_dbus.cpp 2013-04-08 14:07:26 +0000
648+++ tests/test_main_dbus.cpp 2015-10-01 03:52:29 +0000
649@@ -2,6 +2,7 @@
650 #include <gio/gio.h>
651 #include <NuxCore/Logger.h>
652 #include <Nux/Nux.h>
653+#include <UnityCore/GLibDBusNameWatcher.h>
654 #include "test_utils.h"
655
656 #include "config.h"
657@@ -35,7 +36,7 @@
658 g_print ("option parsing failed: %s\n", error->message);
659 return 1;
660 }
661-
662+
663 signal(SIGINT, signal_handler);
664 nux::NuxInitialize (0);
665
666@@ -66,24 +67,12 @@
667 static bool wait_until_test_service_appears()
668 {
669 bool have_name = false;
670-
671- auto callback = [](GDBusConnection * conn,
672- const char * name,
673- const char * name_owner,
674- gpointer user_data)
675- {
676- *(bool*)user_data = true;
677- };
678-
679- g_bus_watch_name(G_BUS_TYPE_SESSION,
680- "com.canonical.Unity.Test",
681- G_BUS_NAME_WATCHER_FLAGS_NONE,
682- callback,
683- NULL,
684- &have_name,
685- NULL);
686-
687- Utils::WaitUntil(have_name, 3);
688+ unity::glib::DBusNameWatcher watcher("com.canonical.Unity.Test");
689+ watcher.appeared.connect([&have_name] (std::string const&, std::string const&) {
690+ have_name = true;
691+ });
692+
693+ Utils::WaitUntil(have_name, 3, "Service has not appeared");
694 EXPECT_TRUE(have_name);
695
696 return have_name;
697@@ -92,6 +81,12 @@
698 static void tell_service_to_exit()
699 {
700 // Ask the service to exit
701+ bool lost_name = false;
702+ unity::glib::DBusNameWatcher watcher("com.canonical.Unity.Test");
703+ watcher.vanished.connect([&lost_name] (std::string const&) {
704+ lost_name = true;
705+ });
706+
707 GDBusConnection* connection = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL);
708 g_dbus_connection_call_sync(connection,
709 "com.canonical.Unity.Test",
710@@ -104,6 +99,9 @@
711 -1,
712 NULL, NULL);
713 g_object_unref(connection);
714+
715+ Utils::WaitUntil(lost_name, 3, "Service is not vanished");
716+ EXPECT_TRUE(lost_name);
717 }
718
719 static void signal_handler(int sig)
720
721=== modified file 'tests/test_result_renderer.cpp'
722--- tests/test_result_renderer.cpp 2014-07-30 00:49:35 +0000
723+++ tests/test_result_renderer.cpp 2015-10-01 03:52:29 +0000
724@@ -79,7 +79,7 @@
725 }
726
727 private:
728- std::auto_ptr<dash::TextureContainer> renderer_;
729+ std::unique_ptr<dash::TextureContainer> renderer_;
730 };
731
732 TEST_F(TestResultRenderer, TestConstruction)
733
734=== modified file 'tests/test_service_panel.cpp'
735--- tests/test_service_panel.cpp 2015-01-14 22:50:25 +0000
736+++ tests/test_service_panel.cpp 2015-10-01 03:52:29 +0000
737@@ -17,6 +17,10 @@
738 " <arg type='" ENTRY_ARRAY_SIGNATURE "' name='state' direction='out'/>"
739 " </method>"
740 "\n"
741+" <method name='GetIconPaths'>"
742+" <arg type='as' name='paths' direction='out'/>"
743+" </method>"
744+"\n"
745 " <signal name='ReSync'>"
746 " <arg type='s' name='indicator_id' />"
747 " </signal>"
748@@ -118,6 +122,10 @@
749 {
750 return g_variant_new("(b)", trigger_resync1_sent_ ? TRUE : FALSE);
751 }
752+ else if (method == "GetIconPaths")
753+ {
754+ return g_variant_new("(as)", nullptr);
755+ }
756
757 return nullptr;
758 }
759
760=== modified file 'tests/test_showdesktop_handler.cpp'
761--- tests/test_showdesktop_handler.cpp 2013-07-23 12:28:01 +0000
762+++ tests/test_showdesktop_handler.cpp 2015-10-01 03:52:29 +0000
763@@ -3,6 +3,7 @@
764 #include <gtest/gtest.h>
765 #include <gmock/gmock.h>
766 #include <UnityShowdesktopHandler.h>
767+#include "test_utils.h"
768
769 using namespace unity;
770 using ::testing::_;
771@@ -404,7 +405,7 @@
772 EXPECT_EQ (ShowdesktopHandler::animating_windows.size (), 1);
773 }
774
775-TEST_F(UnityShowdesktopHandlerTest, DISABLED_TestAnimationOpacity)
776+TEST_F(UnityShowdesktopHandlerTest, UNSTABLE_TEST(TestAnimationOpacity))
777 {
778 MockUnityShowdesktopHandlerWindow mMockWindow;
779
780
781=== modified file 'tests/test_utils.h'
782--- tests/test_utils.h 2014-01-29 14:42:06 +0000
783+++ tests/test_utils.h 2015-10-01 03:52:29 +0000
784@@ -8,6 +8,16 @@
785 #include "GLibWrapper.h"
786 #include "config.h"
787
788+#ifdef UNITY_DEBUG_BUILD
789+#define UNSTABLE_PREFIX UNSTABLE
790+#else
791+#define UNSTABLE_PREFIX DISABLED
792+#endif
793+
794+#define TEST_PREFIX(prefix,test) prefix ## _ ## test
795+#define TEST_EVALUATOR(prefix,test) TEST_PREFIX(prefix,test)
796+#define UNSTABLE_TEST(test) TEST_EVALUATOR(UNSTABLE_PREFIX, test)
797+
798 namespace
799 {
800
801
802=== modified file 'tests/test_xdnd_start_stop_notifier_imp.cpp'
803--- tests/test_xdnd_start_stop_notifier_imp.cpp 2012-11-24 14:28:14 +0000
804+++ tests/test_xdnd_start_stop_notifier_imp.cpp 2015-10-01 03:52:29 +0000
805@@ -47,7 +47,7 @@
806 unity::XdndStartStopNotifierImp xdnd_start_stop_notifier;
807 };
808
809-TEST_F(TestXdndStartStopNotifierImp, DISABLED_SignalStarted)
810+TEST_F(TestXdndStartStopNotifierImp, UNSTABLE_TEST(SignalStarted))
811 {
812 bool signal_received = false;
813 xdnd_start_stop_notifier.started.connect([&](){
814@@ -63,7 +63,7 @@
815 //XTestFakeButtonEvent(display_, 1, False, CurrentTime);
816 }
817
818-TEST_F(TestXdndStartStopNotifierImp, DISABLED_SignalFinished)
819+TEST_F(TestXdndStartStopNotifierImp, UNSTABLE_TEST(SignalFinished))
820 {
821 bool signal_received = false;
822 xdnd_start_stop_notifier.finished.connect([&](){
823
824=== modified file 'unity-shared/GnomeKeyGrabber.cpp'
825--- unity-shared/GnomeKeyGrabber.cpp 2015-03-18 15:04:38 +0000
826+++ unity-shared/GnomeKeyGrabber.cpp 2015-10-01 03:52:29 +0000
827@@ -1,6 +1,6 @@
828 // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
829 /*
830- * Copyright (C) 2013 Canonical Ltd
831+ * Copyright (C) 2013-2015 Canonical Ltd
832 *
833 * This program is free software: you can redistribute it and/or modify
834 * it under the terms of the GNU General Public License version 3 as
835@@ -15,6 +15,7 @@
836 * along with this program. If not, see <http://www.gnu.org/licenses/>.
837 *
838 * Authored by: William Hua <william.hua@canonical.com>
839+ * Marco Trevisan <marco.trevisan@canonical.com>
840 */
841
842 #include "GnomeKeyGrabberImpl.h"
843@@ -63,168 +64,174 @@
844 std::string const DBUS_NAME = "com.canonical.Unity.Test.GnomeKeyGrabber";
845 }
846
847+namespace
848+{
849+inline int compiz_event_timestamp(CompOption::Vector& options) { return options[7].value().i(); }
850+}
851+
852 GnomeGrabber::Impl::Impl(bool test_mode)
853- : shell_server_(test_mode ? testing::DBUS_NAME : shell::DBUS_NAME)
854- , screen_(screen)
855+ : screen_(screen)
856+ , shell_server_(test_mode ? testing::DBUS_NAME : shell::DBUS_NAME)
857 , current_action_id_(0)
858 {
859 shell_server_.AddObjects(shell::INTROSPECTION_XML, shell::DBUS_OBJECT_PATH);
860 shell_object_ = shell_server_.GetObject(shell::DBUS_INTERFACE);
861- shell_object_->SetMethodsCallsHandler(sigc::mem_fun(this, &Impl::onShellMethodCall));
862+ shell_object_->SetMethodsCallsHandlerFull(sigc::mem_fun(this, &Impl::OnShellMethodCall));
863 }
864
865 GnomeGrabber::Impl::~Impl()
866 {
867- if (screen_)
868- {
869- for (auto& action : actions_)
870- screen_->removeAction(&action);
871- }
872-}
873-
874-unsigned int GnomeGrabber::Impl::addAction(CompAction const& action, bool addressable)
875-{
876- ++current_action_id_;
877- actions_.push_back(action);
878- action_ids_.push_back(current_action_id_);
879-
880- if (addressable)
881- {
882- action_ids_by_action_[&action] = current_action_id_;
883- actions_by_action_id_[current_action_id_] = &action;
884- }
885-
886- if (screen_)
887- screen_->addAction(&actions_.back());
888-
889- LOG_DEBUG(logger) << "addAction (\"" << action.keyToString() << "\", " << addressable << ") = " << current_action_id_;
890-
891- return current_action_id_;
892-}
893-
894-bool GnomeGrabber::Impl::removeAction(CompAction const& action)
895-{
896- auto i = action_ids_by_action_.find(&action);
897- return i != action_ids_by_action_.end() && removeAction(i->second);
898-}
899-
900-bool GnomeGrabber::Impl::removeAction(unsigned int action_id)
901-{
902- auto i = std::find(action_ids_.begin(), action_ids_.end(), action_id);
903-
904- if (i != action_ids_.end())
905- {
906- auto j = actions_.begin() + (i - action_ids_.begin());
907- auto k = actions_by_action_id_.find(action_id);
908-
909- LOG_DEBUG(logger) << "removeAction (" << action_id << " \"" << j->keyToString() << "\")";
910-
911- if (screen_)
912- screen_->removeAction(&(*j));
913-
914- if (k != actions_by_action_id_.end())
915- {
916- action_ids_by_action_.erase(k->second);
917- actions_by_action_id_.erase(k);
918- }
919-
920- action_ids_.erase(i);
921- actions_.erase(j);
922- return true;
923- }
924-
925- return false;
926-}
927-
928-GVariant* GnomeGrabber::Impl::onShellMethodCall(std::string const& method, GVariant* parameters)
929+ for (auto& action : actions_)
930+ screen_->removeAction(&action);
931+}
932+
933+uint32_t GnomeGrabber::Impl::NextActionID()
934+{
935+ return ++current_action_id_;
936+}
937+
938+bool GnomeGrabber::Impl::AddAction(CompAction const& action, uint32_t& action_id)
939+{
940+ LOG_DEBUG(logger) << "AddAction (\"" << action.keyToString() << "\") = " << action_id;
941+
942+ if (action.key().toString().empty())
943+ {
944+ LOG_WARN(logger) << "Trying to grab a disabled action, we skip it";
945+ return false;
946+ }
947+
948+ auto it = std::find(actions_.begin(), actions_.end(), action);
949+ if (it != actions_.end())
950+ {
951+ action_id = actions_ids_[it - actions_.begin()];
952+ LOG_DEBUG(logger) << "Key binding \"" << action.keyToString() << "\" is already grabbed, reusing id " << action_id;
953+ return true;
954+ }
955+
956+ if (screen_->addAction(const_cast<CompAction*>(&action)))
957+ {
958+ actions_ids_.push_back(action_id);
959+ actions_.push_back(action);
960+ return true;
961+ }
962+
963+ LOG_ERROR(logger) << "Impossible to grab action \"" << action.keyToString() << "\"";
964+ return false;
965+}
966+
967+uint32_t GnomeGrabber::Impl::AddAction(CompAction const& action)
968+{
969+ auto action_id = NextActionID();
970+ return AddAction(action, action_id) ? action_id : 0;
971+}
972+
973+bool GnomeGrabber::Impl::RemoveAction(CompAction const& action)
974+{
975+ auto it = std::find(actions_.begin(), actions_.end(), action);
976+
977+ if (it != actions_.end())
978+ return RemoveActionByIndex(it - actions_.begin());
979+
980+ return false;
981+}
982+
983+bool GnomeGrabber::Impl::RemoveActionByID(uint32_t action_id)
984+{
985+ if (!action_id)
986+ return false;
987+
988+ auto it = std::find(actions_ids_.begin(), actions_ids_.end(), action_id);
989+
990+ if (it != actions_ids_.end())
991+ return RemoveActionByIndex(it - actions_ids_.begin());
992+
993+ return false;
994+}
995+
996+bool GnomeGrabber::Impl::RemoveActionByIndex(size_t index)
997+{
998+ if (!index || index >= actions_.size())
999+ return false;
1000+
1001+ CompAction* action = &(actions_[index]);
1002+ LOG_DEBUG(logger) << "RemoveAction (\"" << action->keyToString() << "\")";
1003+
1004+ screen_->removeAction(action);
1005+ actions_.erase(actions_.begin() + index);
1006+ actions_ids_.erase(actions_ids_.begin() + index);
1007+
1008+ return true;
1009+}
1010+
1011+GVariant* GnomeGrabber::Impl::OnShellMethodCall(std::string const& method, GVariant* parameters, std::string const& sender, std::string const&)
1012 {
1013 LOG_DEBUG(logger) << "Called method '" << method << "'";
1014
1015 if (method == "GrabAccelerators")
1016 {
1017- if (g_variant_is_of_type(parameters, G_VARIANT_TYPE("(a(su))")))
1018- {
1019- GVariant* variant;
1020- GVariantBuilder builder;
1021- GVariantIter* iterator;
1022- gchar const* accelerator;
1023- guint flags;
1024-
1025- g_variant_builder_init(&builder, G_VARIANT_TYPE("au"));
1026- g_variant_get(parameters, "(a(su))", &iterator);
1027-
1028- while (g_variant_iter_next(iterator, "(&su)", &accelerator, &flags))
1029- g_variant_builder_add(&builder, "u", grabAccelerator(accelerator, flags));
1030-
1031- g_variant_iter_free(iterator);
1032- variant = g_variant_builder_end(&builder);
1033- return g_variant_new_tuple(&variant, 1);
1034- }
1035- else
1036- LOG_WARN(logger) << "Expected arguments of type (a(su))";
1037+ GVariant* variant;
1038+ GVariantBuilder builder;
1039+ GVariantIter* iterator;
1040+ gchar const* accelerator;
1041+ guint flags;
1042+
1043+ g_variant_builder_init(&builder, G_VARIANT_TYPE("au"));
1044+ g_variant_get(parameters, "(a(su))", &iterator);
1045+
1046+ while (g_variant_iter_next(iterator, "(&su)", &accelerator, &flags))
1047+ g_variant_builder_add(&builder, "u", GrabDBusAccelerator(sender, accelerator, flags));
1048+
1049+ g_variant_iter_free(iterator);
1050+ variant = g_variant_builder_end(&builder);
1051+ return g_variant_new_tuple(&variant, 1);
1052 }
1053 else if (method == "GrabAccelerator")
1054 {
1055- if (g_variant_is_of_type(parameters, G_VARIANT_TYPE("(su)")))
1056- {
1057- GVariant* variant;
1058- gchar const* accelerator;
1059- guint flags;
1060+ gchar const* accelerator;
1061+ guint flags;
1062+ g_variant_get(parameters, "(&su)", &accelerator, &flags);
1063
1064- g_variant_get(parameters, "(&su)", &accelerator, &flags);
1065- variant = g_variant_new_uint32(grabAccelerator(accelerator, flags));
1066- return g_variant_new_tuple(&variant, 1);
1067- }
1068- else
1069- LOG_WARN(logger) << "Expected arguments of type (su)";
1070+ if (uint32_t action_id = GrabDBusAccelerator(sender, accelerator, flags))
1071+ return g_variant_new("(u)", action_id);
1072 }
1073 else if (method == "UngrabAccelerator")
1074 {
1075- if (g_variant_is_of_type(parameters, G_VARIANT_TYPE("(u)")))
1076- {
1077- GVariant* variant;
1078- guint action;
1079-
1080- g_variant_get(parameters, "(u)", &action);
1081- variant = g_variant_new_boolean(removeAction(action));
1082- return g_variant_new_tuple(&variant, 1);
1083- }
1084- else
1085- LOG_WARN(logger) << "Expected arguments of type (u)";
1086+ uint32_t action_id;
1087+ g_variant_get(parameters, "(u)", &action_id);
1088+ return g_variant_new("(b)", UnGrabDBusAccelerator(sender, action_id));
1089 }
1090
1091 return nullptr;
1092 }
1093
1094-unsigned int GnomeGrabber::Impl::grabAccelerator(char const* accelerator, unsigned int flags)
1095+uint32_t GnomeGrabber::Impl::GrabDBusAccelerator(std::string const& owner, std::string const& accelerator, uint32_t flags)
1096 {
1097 CompAction action;
1098 action.keyFromString(accelerator);
1099+ uint32_t action_id = NextActionID();
1100+
1101+ LOG_DEBUG(logger) << "GrabDBusAccelerator \"" << accelerator << "\"";
1102
1103 if (action.key().toString().empty())
1104 {
1105- CompString prefixed = "XF86" + CompString(accelerator);
1106+ auto prefixed = "XF86" + accelerator;
1107 LOG_DEBUG(logger) << "Can't grab \"" << accelerator << "\", trying \"" << prefixed << "\"";
1108 action.keyFromString(prefixed);
1109 }
1110- else
1111- {
1112- LOG_DEBUG(logger) << "grabAccelerator \"" << accelerator << "\"";
1113- }
1114
1115- if (!isActionPostponed(action))
1116+ if (!IsActionPostponed(action))
1117 {
1118 action.setState(CompAction::StateInitKey);
1119- action.setInitiate([this](CompAction* action, CompAction::State state, CompOption::Vector& options) {
1120+ action.setInitiate([this, action_id](CompAction* action, CompAction::State state, CompOption::Vector& options) {
1121 LOG_DEBUG(logger) << "pressed \"" << action->keyToString() << "\"";
1122- activateAction(action, 0, options[7].value().i());
1123+ ActivateDBusAction(*action, action_id, 0, compiz_event_timestamp(options));
1124 return true;
1125 });
1126 }
1127 else
1128 {
1129 action.setState(CompAction::StateInitKey | CompAction::StateTermKey);
1130- action.setTerminate([this](CompAction* action, CompAction::State state, CompOption::Vector& options) {
1131+ action.setTerminate([this, action_id](CompAction* action, CompAction::State state, CompOption::Vector& options) {
1132 auto key = action->keyToString();
1133
1134 LOG_DEBUG(logger) << "released \"" << key << "\"";
1135@@ -232,7 +239,7 @@
1136 if (state & CompAction::StateTermTapped)
1137 {
1138 LOG_DEBUG(logger) << "tapped \"" << key << "\"";
1139- activateAction(action, 0, options[7].value().i());
1140+ ActivateDBusAction(*action, action_id, 0, compiz_event_timestamp(options));
1141 return true;
1142 }
1143
1144@@ -240,22 +247,86 @@
1145 });
1146 }
1147
1148- return addAction(action, false);
1149-}
1150-
1151-void GnomeGrabber::Impl::activateAction(CompAction const* action, unsigned device, unsigned timestamp) const
1152-{
1153- ptrdiff_t i = action - &actions_.front();
1154-
1155- if (0 <= i && i < static_cast<ptrdiff_t>(action_ids_.size()))
1156- {
1157- auto action_id = action_ids_[i];
1158- LOG_DEBUG(logger) << "activateAction (" << action_id << " \"" << action->keyToString() << "\")";
1159- shell_object_->EmitSignal("AcceleratorActivated", g_variant_new("(uuu)", action_id, device, timestamp));
1160- }
1161-}
1162-
1163-bool GnomeGrabber::Impl::isActionPostponed(CompAction const& action) const
1164+ if (AddAction(action, action_id))
1165+ {
1166+ auto& owner_actions = actions_by_owner_[owner];
1167+ bool first_insertion = owner_actions.actions.empty();
1168+ owner_actions.actions.insert(action_id);
1169+
1170+ if (first_insertion)
1171+ {
1172+ LOG_DEBUG(logger) << "Initialize dbus watcher for owner '" << owner << "'";
1173+ owner_actions.watcher = std::make_shared<glib::DBusNameWatcher>(owner);
1174+ owner_actions.watcher->vanished.connect([this] (std::string const& name) {
1175+ LOG_DEBUG(logger) << "Signal destination vanished '" << name << "', removing related actions";
1176+ auto it = actions_by_owner_.find(name);
1177+ if (it != actions_by_owner_.end())
1178+ {
1179+ for (auto action_id : it->second.actions)
1180+ RemoveActionForOwner(action_id, name);
1181+
1182+ actions_by_owner_.erase(it);
1183+ }
1184+ });
1185+ }
1186+
1187+ return action_id;
1188+ }
1189+
1190+ return 0;
1191+}
1192+
1193+bool GnomeGrabber::Impl::UnGrabDBusAccelerator(std::string const& owner, uint32_t action_id)
1194+{
1195+ LOG_DEBUG(logger) << "UnGrabDBusAccelerator \"" << action_id << "\"";
1196+
1197+ auto it = actions_by_owner_.find(owner);
1198+ if (it != actions_by_owner_.end())
1199+ {
1200+ auto& actions = it->second.actions;
1201+ actions.erase(action_id);
1202+
1203+ if (actions.empty())
1204+ actions_by_owner_.erase(it);
1205+
1206+ return RemoveActionForOwner(action_id, owner);
1207+ }
1208+
1209+ LOG_WARN(logger) << "Action " << action_id << " was not registered by " << owner << ". "
1210+ << "Unregistration denied";
1211+ return false;
1212+}
1213+
1214+bool GnomeGrabber::Impl::RemoveActionForOwner(uint32_t action_id, std::string const& owner)
1215+{
1216+ for (auto it = actions_by_owner_.begin(); it != actions_by_owner_.end(); ++it)
1217+ {
1218+ if (it->first == owner)
1219+ continue;
1220+
1221+ auto const& actions = it->second.actions;
1222+ if (actions.find(action_id) != actions.end())
1223+ {
1224+ LOG_DEBUG(logger) << "Action " << action_id << " registered for multiple destinations, not removed";
1225+ return false;
1226+ }
1227+ }
1228+
1229+ return RemoveActionByID(action_id);
1230+}
1231+
1232+void GnomeGrabber::Impl::ActivateDBusAction(CompAction const& action, uint32_t action_id, uint32_t device, uint32_t timestamp) const
1233+{
1234+ LOG_DEBUG(logger) << "ActivateAction (" << action_id << " \"" << action.keyToString() << "\")";
1235+
1236+ for (auto const& pair : actions_by_owner_)
1237+ {
1238+ if (pair.second.actions.find(action_id) != pair.second.actions.end())
1239+ shell_object_->EmitSignal("AcceleratorActivated", g_variant_new("(uuu)", action_id, device, timestamp), pair.first);
1240+ }
1241+}
1242+
1243+bool GnomeGrabber::Impl::IsActionPostponed(CompAction const& action) const
1244 {
1245 int keycode = action.key().keycode();
1246 return keycode == 0 || modHandler->keycodeToModifiers(keycode) != 0;
1247@@ -279,14 +350,19 @@
1248 return impl_->actions_;
1249 }
1250
1251-void GnomeGrabber::AddAction(CompAction const& action)
1252-{
1253- impl_->addAction(action);
1254-}
1255-
1256-void GnomeGrabber::RemoveAction(CompAction const& action)
1257-{
1258- impl_->removeAction(action);
1259+uint32_t GnomeGrabber::AddAction(CompAction const& action)
1260+{
1261+ return impl_->AddAction(action);
1262+}
1263+
1264+bool GnomeGrabber::RemoveAction(CompAction const& action)
1265+{
1266+ return impl_->RemoveAction(action);
1267+}
1268+
1269+bool GnomeGrabber::RemoveAction(uint32_t action_id)
1270+{
1271+ return impl_->RemoveActionByID(action_id);
1272 }
1273
1274 } // namespace key
1275
1276=== modified file 'unity-shared/GnomeKeyGrabber.h'
1277--- unity-shared/GnomeKeyGrabber.h 2014-02-12 07:13:01 +0000
1278+++ unity-shared/GnomeKeyGrabber.h 2015-10-01 03:52:29 +0000
1279@@ -32,9 +32,11 @@
1280 GnomeGrabber();
1281 virtual ~GnomeGrabber();
1282
1283- void AddAction(CompAction const&);
1284- void RemoveAction(CompAction const&);
1285- CompAction::Vector& GetActions();
1286+ uint32_t AddAction(CompAction const&) override;
1287+ bool RemoveAction(CompAction const&) override;
1288+ bool RemoveAction(uint32_t action_id) override;
1289+
1290+ CompAction::Vector& GetActions() override;
1291
1292 protected:
1293 struct TestMode {};
1294
1295=== modified file 'unity-shared/GnomeKeyGrabberImpl.h'
1296--- unity-shared/GnomeKeyGrabberImpl.h 2015-03-18 15:04:38 +0000
1297+++ unity-shared/GnomeKeyGrabberImpl.h 2015-10-01 03:52:29 +0000
1298@@ -1,21 +1,22 @@
1299 // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
1300 /*
1301-* Copyright (C) 2013 Canonical Ltd
1302-*
1303-* This program is free software: you can redistribute it and/or modify
1304-* it under the terms of the GNU General Public License version 3 as
1305-* published by the Free Software Foundation.
1306-*
1307-* This program is distributed in the hope that it will be useful,
1308-* but WITHOUT ANY WARRANTY; without even the implied warranty of
1309-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1310-* GNU General Public License for more details.
1311-*
1312-* You should have received a copy of the GNU General Public License
1313-* along with this program. If not, see <http://www.gnu.org/licenses/>.
1314-*
1315-* Authored by: William Hua <william.hua@canonical.com>
1316-*/
1317+ * Copyright (C) 2013-2015 Canonical Ltd
1318+ *
1319+ * This program is free software: you can redistribute it and/or modify
1320+ * it under the terms of the GNU General Public License version 3 as
1321+ * published by the Free Software Foundation.
1322+ *
1323+ * This program is distributed in the hope that it will be useful,
1324+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1325+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1326+ * GNU General Public License for more details.
1327+ *
1328+ * You should have received a copy of the GNU General Public License
1329+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1330+ *
1331+ * Authored by: William Hua <william.hua@canonical.com>
1332+ * Marco Trevisan <marco.trevisan@canonical.com>
1333+ */
1334
1335 #ifndef __GNOME_KEY_GRABBER_IMPL_H__
1336 #define __GNOME_KEY_GRABBER_IMPL_H__
1337@@ -23,8 +24,10 @@
1338 #include "GnomeKeyGrabber.h"
1339
1340 #include <unordered_map>
1341+#include <unordered_set>
1342 #include <UnityCore/GLibDBusProxy.h>
1343 #include <UnityCore/GLibDBusServer.h>
1344+#include <UnityCore/GLibDBusNameWatcher.h>
1345
1346 namespace unity
1347 {
1348@@ -36,26 +39,34 @@
1349 Impl(bool test_mode = false);
1350 ~Impl();
1351
1352+ uint32_t NextActionID();
1353+
1354+ bool AddAction(CompAction const& action, uint32_t& action_id);
1355+ uint32_t AddAction(CompAction const& action);
1356+
1357+ bool RemoveAction(CompAction const& action);
1358+ bool RemoveActionByID(uint32_t action_id);
1359+ bool RemoveActionByIndex(size_t index);
1360+
1361+ GVariant* OnShellMethodCall(std::string const& method, GVariant* parameters, std::string const& sender, std::string const&);
1362+ uint32_t GrabDBusAccelerator(std::string const& owner, std::string const& accelerator, uint32_t flags);
1363+ bool UnGrabDBusAccelerator(std::string const& sender, uint32_t action_id);
1364+ void ActivateDBusAction(CompAction const& action, uint32_t id, uint32_t device, uint32_t timestamp) const;
1365+ bool RemoveActionForOwner(uint32_t action_id, std::string const& owner);
1366+
1367+ bool IsActionPostponed(CompAction const& action) const;
1368+
1369+ CompScreen* screen_;
1370+
1371 glib::DBusServer shell_server_;
1372 glib::DBusObject::Ptr shell_object_;
1373
1374- CompScreen* screen_;
1375+ uint32_t current_action_id_;
1376+ std::vector<uint32_t> actions_ids_;
1377 CompAction::Vector actions_;
1378- std::vector<unsigned int> action_ids_;
1379- unsigned int current_action_id_;
1380-
1381- std::unordered_map<CompAction const*, unsigned int> action_ids_by_action_;
1382- std::unordered_map<unsigned int, CompAction const*> actions_by_action_id_;
1383-
1384- unsigned int addAction(CompAction const& action, bool addressable = true);
1385- bool removeAction(CompAction const& action);
1386- bool removeAction(unsigned int action_id);
1387-
1388- GVariant* onShellMethodCall(std::string const& method, GVariant* parameters);
1389- unsigned int grabAccelerator(char const* accelerator, unsigned int flags);
1390- void activateAction(CompAction const* action, unsigned device, unsigned timestamp) const;
1391-
1392- bool isActionPostponed(CompAction const& action) const;
1393+
1394+ struct OwnerActions { glib::DBusNameWatcher::Ptr watcher; std::unordered_set<uint32_t> actions; };
1395+ std::unordered_map<std::string, OwnerActions> actions_by_owner_;
1396 };
1397
1398 } // namespace key
1399
1400=== modified file 'unity-shared/KeyGrabber.h'
1401--- unity-shared/KeyGrabber.h 2014-02-12 07:13:01 +0000
1402+++ unity-shared/KeyGrabber.h 2015-10-01 03:52:29 +0000
1403@@ -32,8 +32,10 @@
1404 typedef std::shared_ptr<Grabber> Ptr;
1405 virtual ~Grabber() = default;
1406
1407- virtual void AddAction(CompAction const&) = 0;
1408- virtual void RemoveAction(CompAction const&) = 0;
1409+ virtual uint32_t AddAction(CompAction const&) = 0;
1410+ virtual bool RemoveAction(CompAction const&) = 0;
1411+ virtual bool RemoveAction(uint32_t id) = 0;
1412+
1413 virtual CompAction::Vector& GetActions() = 0;
1414 };
1415
1416
1417=== modified file 'unity-shared/MenuManager.cpp'
1418--- unity-shared/MenuManager.cpp 2015-09-17 16:44:26 +0000
1419+++ unity-shared/MenuManager.cpp 2015-10-01 03:52:29 +0000
1420@@ -142,18 +142,18 @@
1421 {
1422 auto key = gdk_keyval_to_lower(gdk_unicode_to_keyval(mnemonic));
1423 glib::String accelerator(gtk_accelerator_name(key, GDK_MOD1_MASK));
1424- auto action = std::make_shared<CompAction>();
1425 auto const& id = entry->id();
1426
1427- action->keyFromString(accelerator);
1428- action->setState(CompAction::StateInitKey);
1429- action->setInitiate([this, id] (CompAction* action, CompAction::State, CompOption::Vector&) {
1430+ CompAction action;
1431+ action.keyFromString(accelerator);
1432+ action.setState(CompAction::StateInitKey);
1433+ action.setInitiate([this, id] (CompAction* action, CompAction::State, CompOption::Vector&) {
1434 LOG_DEBUG(logger) << "pressed \"" << action->keyToString() << "\"";
1435 return parent_->key_activate_entry.emit(id);
1436 });
1437
1438- entry_actions_.insert({entry, action});
1439- key_grabber_->AddAction(*action);
1440+ if (uint32_t action_id = key_grabber_->AddAction(action))
1441+ entry_actions_.insert({entry, action_id});
1442 }
1443 }
1444
1445@@ -163,7 +163,7 @@
1446
1447 if (it != entry_actions_.end())
1448 {
1449- key_grabber_->RemoveAction(*it->second);
1450+ key_grabber_->RemoveAction(it->second);
1451 entry_actions_.erase(it);
1452 }
1453 }
1454@@ -172,7 +172,7 @@
1455 {
1456 for (auto it = entry_actions_.begin(); it != entry_actions_.end();)
1457 {
1458- key_grabber_->RemoveAction(*it->second);
1459+ key_grabber_->RemoveAction(it->second);
1460 it = entry_actions_.erase(it);
1461 }
1462 }
1463@@ -240,7 +240,7 @@
1464 connection::Wrapper active_win_conn_;
1465 glib::Object<GSettings> settings_;
1466 glib::SignalManager signals_;
1467- std::unordered_map<indicator::Entry::Ptr, std::shared_ptr<CompAction>> entry_actions_;
1468+ std::unordered_map<indicator::Entry::Ptr, uint32_t> entry_actions_;
1469 };
1470
1471 Manager::Manager(Indicators::Ptr const& indicators, key::Grabber::Ptr const& grabber)
1472
1473=== modified file 'unity-standalone/StandaloneUnity.cpp'
1474--- unity-standalone/StandaloneUnity.cpp 2014-02-25 22:10:53 +0000
1475+++ unity-standalone/StandaloneUnity.cpp 2015-10-01 03:52:29 +0000
1476@@ -72,12 +72,10 @@
1477
1478 struct StandaloneKeyGrabber : key::Grabber
1479 {
1480- CompAction::Vector& GetActions() { return actions_; }
1481- void AddAction(CompAction const&) {}
1482- void RemoveAction(CompAction const&) {}
1483-
1484- private:
1485- CompAction::Vector actions_;
1486+ CompAction::Vector& GetActions() override { return noActions(); }
1487+ uint32_t AddAction(CompAction const&) override { return 0; };
1488+ bool RemoveAction(CompAction const&) override { return false; };
1489+ bool RemoveAction(uint32_t id) override { return false; };
1490 };
1491
1492 class UnityStandalone