summaryrefslogtreecommitdiff
diff options
-rw-r--r--CMakeLists.txt4
-rw-r--r--UnityCore/CMakeLists.txt2
-rw-r--r--UnityCore/GLibDBusNameWatcher.cpp44
-rw-r--r--UnityCore/GLibDBusNameWatcher.h54
-rw-r--r--UnityCore/GLibDBusProxy.cpp10
-rw-r--r--UnityCore/GLibDBusServer.cpp43
-rw-r--r--UnityCore/GLibDBusServer.h12
-rw-r--r--panel/StandalonePanel.cpp10
-rw-r--r--tests/CMakeLists.txt2
-rw-r--r--tests/autopilot/unity/tests/test_gnome_key_grabber.py22
-rw-r--r--tests/mock_key_grabber.h5
-rw-r--r--tests/test_glib_dbus_proxy.cpp67
-rw-r--r--tests/test_gnome_session_manager.cpp2
-rw-r--r--tests/test_icon_loader.cpp16
-rw-r--r--tests/test_main_dbus.cpp34
-rw-r--r--tests/test_result_renderer.cpp2
-rw-r--r--tests/test_service_panel.cpp8
-rw-r--r--tests/test_showdesktop_handler.cpp3
-rw-r--r--tests/test_utils.h10
-rw-r--r--tests/test_xdnd_start_stop_notifier_imp.cpp4
-rw-r--r--unity-shared/GnomeKeyGrabber.cpp284
-rw-r--r--unity-shared/GnomeKeyGrabber.h8
-rw-r--r--unity-shared/GnomeKeyGrabberImpl.h73
-rw-r--r--unity-shared/KeyGrabber.h6
-rw-r--r--unity-shared/MenuManager.cpp18
-rw-r--r--unity-standalone/StandaloneUnity.cpp10
26 files changed, 490 insertions, 263 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c7baf29f4..7b807a4ff 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -15,8 +15,8 @@ set (UNITY_VERSION "${UNITY_MAJOR}.${UNITY_MINOR}.${UNITY_MICRO}")
set (UNITY_API_VERSION "6.0")
set (UNITY_COMPONENTS_VERSION "6")
-set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGNOME_DESKTOP_USE_UNSTABLE_API -std=c++0x -fno-permissive")
-set (CMAKE_CXX_FLAGS_DEBUG "-g3")
+set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGNOME_DESKTOP_USE_UNSTABLE_API -std=c++11 -fno-permissive")
+set (CMAKE_CXX_FLAGS_DEBUG "-g3 -DUNITY_DEBUG_BUILD")
set (CMAKE_CXX_FLAGS_RELEASE "")
option(
diff --git a/UnityCore/CMakeLists.txt b/UnityCore/CMakeLists.txt
index 92191c0d5..f055790d3 100644
--- a/UnityCore/CMakeLists.txt
+++ b/UnityCore/CMakeLists.txt
@@ -25,6 +25,7 @@ set (CORE_HEADERS
Filter.h
Filters.h
GenericPreview.h
+ GLibDBusNameWatcher.h
GLibDBusProxy.h
GLibDBusServer.h
GLibSignal.h
@@ -80,6 +81,7 @@ set (CORE_SOURCES
Filter.cpp
Filters.cpp
GenericPreview.cpp
+ GLibDBusNameWatcher.cpp
GLibDBusProxy.cpp
GLibDBusServer.cpp
GLibSignal.cpp
diff --git a/UnityCore/GLibDBusNameWatcher.cpp b/UnityCore/GLibDBusNameWatcher.cpp
new file mode 100644
index 000000000..92f311210
--- /dev/null
+++ b/UnityCore/GLibDBusNameWatcher.cpp
@@ -0,0 +1,44 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/*
+ * Copyright (C) 2015 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Marco Trevisan (Treviño) <marco.trevisan@canonical.com>
+ */
+
+#include "GLibDBusNameWatcher.h"
+#include "GLibWrapper.h"
+
+namespace unity
+{
+namespace glib
+{
+
+DBusNameWatcher::DBusNameWatcher(std::string const& name, GBusType bus_type, GBusNameWatcherFlags flags)
+ : watcher_id_(g_bus_watch_name(bus_type, name.c_str(), flags,
+ [] (GDBusConnection *connection, const gchar *name, const gchar *name_owner, gpointer self) {
+ static_cast<DBusNameWatcher*>(self)->appeared.emit(gchar_to_string(name), gchar_to_string(name_owner));
+ },
+ [] (GDBusConnection *connection, const gchar *name, gpointer self) {
+ static_cast<DBusNameWatcher*>(self)->vanished.emit(gchar_to_string(name));
+ }, this, nullptr))
+{}
+
+DBusNameWatcher::~DBusNameWatcher()
+{
+ g_bus_unwatch_name(watcher_id_);
+}
+
+} // namespace glib
+} // namespace unity
diff --git a/UnityCore/GLibDBusNameWatcher.h b/UnityCore/GLibDBusNameWatcher.h
new file mode 100644
index 000000000..b5901d3d4
--- /dev/null
+++ b/UnityCore/GLibDBusNameWatcher.h
@@ -0,0 +1,54 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/*
+ * Copyright (C) 2015 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Marco Trevisan (Treviño) <marco.trevisan@canonical.com>
+ */
+
+#ifndef UNITY_GLIB_DBUS_NAME_WATCHER_H
+#define UNITY_GLIB_DBUS_NAME_WATCHER_H
+
+#include <gio/gio.h>
+#include <memory>
+#include <sigc++/signal.h>
+
+namespace unity
+{
+namespace glib
+{
+
+class DBusNameWatcher
+{
+public:
+ typedef std::shared_ptr<DBusNameWatcher> Ptr;
+
+ DBusNameWatcher(std::string const& name, GBusType bus_type = G_BUS_TYPE_SESSION, GBusNameWatcherFlags flags = G_BUS_NAME_WATCHER_FLAGS_NONE);
+ virtual ~DBusNameWatcher();
+
+ sigc::signal<void, std::string const& /* name*/, std::string const& /* name owner*/> appeared;
+ sigc::signal<void, std::string const& /* name */> vanished;
+
+private:
+ // not copyable class
+ DBusNameWatcher(DBusNameWatcher const&) = delete;
+ DBusNameWatcher& operator=(DBusNameWatcher const&) = delete;
+
+ uint32_t watcher_id_;
+};
+
+} // namespace glib
+} // namespace unity
+
+#endif //UNITY_GLIB_DBUS_NAME_WATCHER_H
diff --git a/UnityCore/GLibDBusProxy.cpp b/UnityCore/GLibDBusProxy.cpp
index fabef7d48..1cd6f4d3d 100644
--- a/UnityCore/GLibDBusProxy.cpp
+++ b/UnityCore/GLibDBusProxy.cpp
@@ -344,7 +344,8 @@ void DBusProxy::Impl::WaitForProxy(GCancellable* cancellable,
// wait for the signal
*con = proxy_acquired.connect([con, canc, timeout, callback] ()
{
- if (!g_cancellable_is_cancelled(canc)) callback(glib::Error());
+ if (!g_cancellable_is_cancelled(canc))
+ callback(glib::Error());
timeout->Remove();
con->disconnect();
@@ -390,12 +391,15 @@ void DBusProxy::Impl::Call(string const& method_name,
if (!proxy_)
{
glib::Variant sinked_parameters(parameters);
- glib::Object<GCancellable>canc(target_canc, glib::AddRef());
+ glib::Object<GCancellable> canc(target_canc, glib::AddRef());
+
WaitForProxy(canc, timeout_msec, [this, method_name, sinked_parameters, callback, canc, flags, timeout_msec] (glib::Error const& err)
{
if (err)
{
- callback(glib::Variant(), err);
+ if (callback)
+ callback(glib::Variant(), err);
+
LOG_WARNING(logger) << "Cannot call method " << method_name
<< ": " << err;
}
diff --git a/UnityCore/GLibDBusServer.cpp b/UnityCore/GLibDBusServer.cpp
index 6d01f5994..49b70d7c0 100644
--- a/UnityCore/GLibDBusServer.cpp
+++ b/UnityCore/GLibDBusServer.cpp
@@ -87,7 +87,7 @@ struct DBusObject::Impl
if (self->method_cb_)
{
- ret = self->method_cb_(method_name ? method_name : "", parameters);
+ ret = self->method_cb_(gchar_to_string(method_name), parameters, gchar_to_string(sender), gchar_to_string(object_path));
LOG_INFO(logger_o) << "Called method: '" << method_name << " " << parameters
<< "' on object '" << object_path << "' with interface '"
@@ -295,13 +295,14 @@ struct DBusObject::Impl
void EmitGenericSignal(glib::Object<GDBusConnection> const& conn, std::string const& path,
std::string const& interface, std::string const& signal,
- GVariant* parameters = nullptr)
+ GVariant* parameters = nullptr, std::string const& dest = "")
{
LOG_INFO(logger_o) << "Emitting signal '" << signal << "'" << " for the interface "
<< "'" << interface << "' on object path '" << path << "'";
glib::Error error;
- g_dbus_connection_emit_signal(conn, nullptr, path.c_str(), interface.c_str(),
+ g_dbus_connection_emit_signal(conn, dest.empty() ? nullptr : dest.c_str(),
+ path.c_str(), interface.c_str(),
signal.c_str(), parameters, &error);
if (error)
@@ -312,7 +313,7 @@ struct DBusObject::Impl
}
}
- void EmitSignal(std::string const& signal, GVariant* parameters, std::string const& path)
+ void EmitSignal(std::string const& signal, GVariant* parameters, std::string const& dest, std::string const& path)
{
glib::Variant reffed_params(parameters);
@@ -333,7 +334,7 @@ struct DBusObject::Impl
return;
}
- EmitGenericSignal(conn_it->second, path, InterfaceName(), signal, parameters);
+ EmitGenericSignal(conn_it->second, path, InterfaceName(), signal, parameters, dest);
}
else
{
@@ -343,7 +344,7 @@ struct DBusObject::Impl
auto const& obj_path = pair.first;
auto const& conn = pair.second;
- EmitGenericSignal(conn, obj_path, InterfaceName(), signal, params);
+ EmitGenericSignal(conn, obj_path, InterfaceName(), signal, params, dest);
}
}
}
@@ -401,7 +402,7 @@ struct DBusObject::Impl
}
DBusObject* object_;
- MethodCallback method_cb_;
+ MethodCallbackFull method_cb_;
PropertyGetterCallback property_get_cb_;
PropertySetterCallback property_set_cb_;
@@ -420,6 +421,18 @@ DBusObject::~DBusObject()
void DBusObject::SetMethodsCallsHandler(MethodCallback const& func)
{
+ impl_->method_cb_ = nullptr;
+
+ if (func)
+ {
+ impl_->method_cb_ = [func] (std::string const& method, GVariant* parameters, std::string const&, std::string const&) {
+ return func(method, parameters);
+ };
+ }
+}
+
+void DBusObject::SetMethodsCallsHandlerFull(MethodCallbackFull const& func)
+{
impl_->method_cb_ = func;
}
@@ -448,9 +461,9 @@ void DBusObject::UnRegister(std::string const& path)
impl_->UnRegister(path);
}
-void DBusObject::EmitSignal(std::string const& signal, GVariant* parameters, std::string const& path)
+void DBusObject::EmitSignal(std::string const& signal, GVariant* parameters, std::string const& dest, std::string const& path)
{
- impl_->EmitSignal(signal, parameters, path);
+ impl_->EmitSignal(signal, parameters, dest, path);
}
void DBusObject::EmitPropertyChanged(std::string const& property, std::string const& path)
@@ -648,12 +661,10 @@ struct DBusServer::Impl
return DBusObject::Ptr();
}
- void EmitSignal(std::string const& interface, std::string const& signal, GVariant* parameters)
+ void EmitSignal(std::string const& interface, std::string const& signal, GVariant* parameters, std::string const& dest)
{
- auto const& obj = GetObject(interface);
-
- if (obj)
- obj->EmitSignal(signal, parameters);
+ if (DBusObject::Ptr const& obj = GetObject(interface))
+ obj->EmitSignal(signal, parameters, dest);
}
DBusServer* server_;
@@ -735,9 +746,9 @@ DBusObject::Ptr DBusServer::GetObject(std::string const& interface) const
return impl_->GetObject(interface);
}
-void DBusServer::EmitSignal(std::string const& interface, std::string const& signal, GVariant* parameters)
+void DBusServer::EmitSignal(std::string const& interface, std::string const& signal, GVariant* parameters, std::string const& dest)
{
- impl_->EmitSignal(interface, signal, parameters);
+ impl_->EmitSignal(interface, signal, parameters, dest);
}
} // namespace glib
diff --git a/UnityCore/GLibDBusServer.h b/UnityCore/GLibDBusServer.h
index 8957861be..b064c4360 100644
--- a/UnityCore/GLibDBusServer.h
+++ b/UnityCore/GLibDBusServer.h
@@ -40,11 +40,13 @@ public:
DBusObject(std::string const& introspection_xml, std::string const& interface_name);
virtual ~DBusObject();
- typedef std::function<GVariant*(std::string const&, GVariant*)> MethodCallback;
- typedef std::function<GVariant*(std::string const&)> PropertyGetterCallback;
- typedef std::function<bool(std::string const&, GVariant*)> PropertySetterCallback;
+ typedef std::function<GVariant*(std::string const& /*method*/, GVariant* /*parameters*/)> MethodCallback;
+ typedef std::function<GVariant*(std::string const& /*method*/, GVariant* /*parameters*/, std::string const& /*sender*/, std::string const& /*object_path*/)> MethodCallbackFull;
+ typedef std::function<GVariant*(std::string const& /*name*/)> PropertyGetterCallback;
+ typedef std::function<bool(std::string const& /*name*/, GVariant* /*value*/)> PropertySetterCallback;
void SetMethodsCallsHandler(MethodCallback const&);
+ void SetMethodsCallsHandlerFull(MethodCallbackFull const&);
void SetPropertyGetter(PropertyGetterCallback const&);
void SetPropertySetter(PropertySetterCallback const&);
@@ -53,7 +55,7 @@ public:
bool Register(glib::Object<GDBusConnection> const&, std::string const& path);
void UnRegister(std::string const& path = "");
- void EmitSignal(std::string const& signal, GVariant* parameters = nullptr, std::string const& path = "");
+ void EmitSignal(std::string const& signal, GVariant* parameters = nullptr, std::string const& dest = "", std::string const& path = "");
void EmitPropertyChanged(std::string const& property, std::string const& path = "");
sigc::signal<void, std::string const&> registered;
@@ -91,7 +93,7 @@ public:
std::list<DBusObject::Ptr> GetObjects() const;
DBusObject::Ptr GetObject(std::string const& interface) const;
- void EmitSignal(std::string const& interface, std::string const& signal, GVariant* parameters = nullptr);
+ void EmitSignal(std::string const& interface, std::string const& signal, GVariant* parameters = nullptr, std::string const& dest = "");
bool IsConnected() const;
std::string const& Name() const;
diff --git a/panel/StandalonePanel.cpp b/panel/StandalonePanel.cpp
index 69311390a..e13460240 100644
--- a/panel/StandalonePanel.cpp
+++ b/panel/StandalonePanel.cpp
@@ -63,12 +63,10 @@ private:
struct MockKeyGrabber : key::Grabber
{
- CompAction::Vector& GetActions() { return actions_; }
- void AddAction(CompAction const&) {}
- void RemoveAction(CompAction const&) {}
-
- private:
- CompAction::Vector actions_;
+ CompAction::Vector& GetActions() override { return noActions(); }
+ uint32_t AddAction(CompAction const&) override { return 0; };
+ bool RemoveAction(CompAction const&) override { return false; };
+ bool RemoveAction(uint32_t id) override { return false; };
};
void Init()
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 831761352..5fea35009 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -355,7 +355,7 @@ if (ENABLE_X_SUPPORT)
endif (ENABLE_X_SUPPORT)
set (GTEST_TEST_COMMAND_XLESS ./test-gtest-xless --gtest_output=xml:./test-gtest-xless.xml)
set (GTEST_TEST_COMMAND_SLOW ./test-gtest-slow --gtest_output=xml:./test-gtest-slow.xml)
-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*)
+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*)
set (TEST_COMMAND_XLESS
${GTEST_TEST_COMMAND_XLESS}
diff --git a/tests/autopilot/unity/tests/test_gnome_key_grabber.py b/tests/autopilot/unity/tests/test_gnome_key_grabber.py
index 8287487ed..d7c49f60d 100644
--- a/tests/autopilot/unity/tests/test_gnome_key_grabber.py
+++ b/tests/autopilot/unity/tests/test_gnome_key_grabber.py
@@ -154,20 +154,12 @@ class GnomeKeyGrabberTests(unity.tests.UnityTestCase):
self.addCleanup(clean_up_test_grab_same_accelerator)
- for accelerator in accelerators:
- # Check that accelerator works
- self.assertTrue(self.press_accelerator(accelerator))
-
- # Remove accelerator
- log.info('ungrabbing %s' % accelerator)
- self.assertTrue(self.interface.UngrabAccelerator(accelerator.action))
-
- # This accelerator cannot activate any more
- self.activatable.remove(accelerator.action)
+ # Check that accelerator works
+ self.assertTrue(self.press_accelerator(accelerator))
- # Add them all again for one final check
- for accelerator in accelerators:
- self.activatable.add(accelerator.action)
+ # Remove accelerator
+ log.info('ungrabbing %s' % accelerator)
+ self.assertTrue(self.interface.UngrabAccelerator(accelerator.action))
- # Check that signal was not emitted
- self.assertFalse(self.press_accelerator(accelerators[0]))
+ for accelerator in accelerators[1:]:
+ self.assertFalse(self.press_accelerator(accelerator))
diff --git a/tests/mock_key_grabber.h b/tests/mock_key_grabber.h
index 17031e737..2c271ca56 100644
--- a/tests/mock_key_grabber.h
+++ b/tests/mock_key_grabber.h
@@ -39,8 +39,9 @@ struct MockGrabber : Grabber
}
MOCK_METHOD0(GetActions, CompAction::Vector&());
- MOCK_METHOD1(AddAction, void(CompAction const&));
- MOCK_METHOD1(RemoveAction, void(CompAction const&));
+ MOCK_METHOD1(AddAction, uint32_t(CompAction const&));
+ MOCK_METHOD1(RemoveAction, bool(CompAction const&));
+ MOCK_METHOD1(RemoveAction, bool(uint32_t));
CompAction::Vector actions_;
};
diff --git a/tests/test_glib_dbus_proxy.cpp b/tests/test_glib_dbus_proxy.cpp
index 6afa2d3fd..09fe7e314 100644
--- a/tests/test_glib_dbus_proxy.cpp
+++ b/tests/test_glib_dbus_proxy.cpp
@@ -88,73 +88,85 @@ TEST_F(TestGDBusProxy, TestMethodReturn)
Utils::WaitUntilMSec(got_result_return);
Utils::WaitUntilMSec(got_signal_return);
-
+
EXPECT_EQ(returned_result, expected_return);
EXPECT_EQ(returned_signal, expected_return);
}
-TEST_F(TestGDBusProxy, TestCancelling)
+TEST_F(TestGDBusProxy, TestCancellingBeforeConnecting)
{
- std::string call_return;
// method callback
- auto method_connection = [&](GVariant *variant)
+ auto method_connection = [this](GVariant *variant, glib::Error const& e)
{
- if (variant != nullptr)
- {
- call_return = g_variant_get_string(g_variant_get_child_value(variant, 0), NULL);
- }
+ got_result_return = true;
+ };
+
+ Utils::WaitUntilMSec(sigc::mem_fun(proxy, &glib::DBusProxy::IsConnected));
+
+ glib::Cancellable cancellable;
+ proxy.CallBegin("TestMethod", g_variant_new("(s)", "TestStringTestString"),
+ method_connection, cancellable);
+
+ cancellable.Cancel();
+
+ Utils::WaitPendingEvents();
+ EXPECT_FALSE(got_result_return);
+}
+TEST_F(TestGDBusProxy, TestCancellingAfterConnecting)
+{
+ // method callback
+ auto method_connection = [this](GVariant *variant, glib::Error const& e)
+ {
got_result_return = true;
};
EXPECT_FALSE(proxy.IsConnected()); // we shouldn't be connected yet
+
glib::Cancellable cancellable;
- // but this has to work eitherway
- proxy.Call("TestMethod", g_variant_new("(s)", "TestStringTestString"),
- method_connection, cancellable);
+ proxy.CallBegin("TestMethod", g_variant_new("(s)", "TestStringTestString"),
+ method_connection, cancellable);
- // this could mostly cause the next test to fail
+ Utils::WaitUntilMSec(sigc::mem_fun(proxy, &glib::DBusProxy::IsConnected));
cancellable.Cancel();
+
+ Utils::WaitPendingEvents();
EXPECT_FALSE(got_result_return);
}
-TEST_F(TestGDBusProxy, TestAcquiring)
+TEST_F(TestGDBusProxy, TestMultipleCalls)
{
const int NUM_REQUESTS = 10;
int completed = 0;
std::string call_return;
// method callback
- auto method_connection = [&](GVariant* variant, glib::Error const& err)
+ auto method_connection = [&](GVariant* variant)
{
- if (variant != nullptr)
- {
- call_return = g_variant_get_string(g_variant_get_child_value(variant, 0), NULL);
- }
-
if (++completed >= NUM_REQUESTS) got_result_return = true;
};
EXPECT_FALSE(proxy.IsConnected()); // we shouldn't be connected yet
for (int i = 0; i < NUM_REQUESTS; i++)
- {
- proxy.CallBegin("TestMethod", g_variant_new("(s)", "TestStringTestString"),
- method_connection, nullptr);
- Utils::WaitForTimeoutMSec(150);
- }
- Utils::WaitUntilMSec(got_result_return, 2);
+ proxy.Call("TestMethod", g_variant_new("(s)", "TestStringTestString"), method_connection, nullptr);
+
+ Utils::WaitPendingEvents();
+ Utils::WaitUntilMSec(got_result_return, 150, G_STRLOC);
+ EXPECT_EQ(completed, NUM_REQUESTS);
}
TEST_F(TestGDBusProxyInvalidService, TestTimeouting)
{
std::string call_return;
+ bool error;
// method callback
- auto method_connection = [&](GVariant* variant, glib::Error const& err)
+ auto method_connection = [&](GVariant* variant, glib::Error const& e)
{
if (variant != nullptr)
{
call_return = g_variant_get_string(g_variant_get_child_value(variant, 0), NULL);
}
+ error = e;
got_result_return = true;
};
@@ -168,6 +180,7 @@ TEST_F(TestGDBusProxyInvalidService, TestTimeouting)
Utils::WaitUntilMSec(got_result_return);
EXPECT_EQ(call_return, "");
+ EXPECT_TRUE(error);
}
TEST_F(TestGDBusProxy, TestMethodCall)
@@ -190,7 +203,7 @@ TEST_F(TestGDBusProxy, TestMethodCall)
method_connection);
Utils::WaitUntilMSec(got_result_return);
-
+
EXPECT_TRUE(proxy.IsConnected());
EXPECT_EQ("TestStringTestString", call_return);
}
diff --git a/tests/test_gnome_session_manager.cpp b/tests/test_gnome_session_manager.cpp
index 05d217a42..d44c3b7ec 100644
--- a/tests/test_gnome_session_manager.cpp
+++ b/tests/test_gnome_session_manager.cpp
@@ -1090,7 +1090,7 @@ TEST_F(TestGnomeSessionManager, LogindUnLock)
EXPECT_TRUE(unlock_emitted);
}
-TEST_F(TestGnomeSessionManager, NoLockWhenLockingDisabled)
+TEST_F(TestGnomeSessionManager, UNSTABLE_TEST(NoLockWhenLockingDisabled))
{
bool lock_emitted = false;
bool screensaver_emitted = false;
diff --git a/tests/test_icon_loader.cpp b/tests/test_icon_loader.cpp
index c817832aa..e14a67620 100644
--- a/tests/test_icon_loader.cpp
+++ b/tests/test_icon_loader.cpp
@@ -53,6 +53,7 @@ struct LoadResult
void CheckResults(std::vector<LoadResult> const& results)
{
+ Utils::WaitPendingEvents(WAIT_TIMEOUT);
Utils::WaitUntilMSec([&results] {
bool got_all = true;
for (auto const& result : results)
@@ -101,8 +102,7 @@ TEST_F(TestIconLoader, TestGetDefault)
EXPECT_EQ(&icon_loader, &IconLoader::GetDefault());
}
-// FIXME: Disabled due to issues on Jenkins using GLibDBusProxy (lp:1224643)
-TEST_F(TestIconLoader, DISABLED_TestGetOneIcon)
+TEST_F(TestIconLoader, UNSTABLE_TEST(TestGetOneIcon))
{
LoadResult load_result;
@@ -110,13 +110,13 @@ TEST_F(TestIconLoader, DISABLED_TestGetOneIcon)
&LoadResult::IconLoaded));
handles_.push_back(handle);
+ Utils::WaitPendingEvents(WAIT_TIMEOUT);
Utils::WaitUntilMSec(load_result.got_callback, WAIT_TIMEOUT);
EXPECT_TRUE(load_result.got_callback);
EXPECT_TRUE(IsValidPixbuf(load_result.pixbuf));
}
-// FIXME: Disabled due to issues on Jenkins using GLibDBusProxy (lp:1224643)
-TEST_F(TestIconLoader, DISABLED_TestGetAnnotatedIcon)
+TEST_F(TestIconLoader, UNSTABLE_TEST(TestGetAnnotatedIcon))
{
LoadResult load_result;
@@ -124,13 +124,13 @@ TEST_F(TestIconLoader, DISABLED_TestGetAnnotatedIcon)
&LoadResult::IconLoaded));
handles_.push_back(handle);
+ Utils::WaitPendingEvents(WAIT_TIMEOUT);
Utils::WaitUntilMSec(load_result.got_callback, WAIT_TIMEOUT);
EXPECT_TRUE(load_result.got_callback);
EXPECT_TRUE(IsValidPixbuf(load_result.pixbuf));
}
-// FIXME: Disabled due to issues on Jenkins using GLibDBusProxy (lp:1224643)
-TEST_F(TestIconLoader, DISABLED_TestGetColorizedIcon)
+TEST_F(TestIconLoader, UNSTABLE_TEST(TestGetColorizedIcon))
{
LoadResult load_result;
@@ -138,6 +138,7 @@ TEST_F(TestIconLoader, DISABLED_TestGetColorizedIcon)
&LoadResult::IconLoaded));
handles_.push_back(handle);
+ Utils::WaitPendingEvents(WAIT_TIMEOUT);
Utils::WaitUntilMSec(load_result.got_callback, WAIT_TIMEOUT);
EXPECT_TRUE(load_result.got_callback);
EXPECT_TRUE(IsValidPixbuf(load_result.pixbuf));
@@ -173,8 +174,7 @@ TEST_F(TestIconLoader, TestGetOneIconManyTimes)
CheckResults(results);
}
-// Disabled until we have the new thread safe lp:fontconfig
-TEST_F(TestIconLoader, DISABLED_TestGetManyIcons)
+TEST_F(TestIconLoader, TestGetManyIcons)
{
std::vector<LoadResult> results;
int i = 0;
diff --git a/tests/test_main_dbus.cpp b/tests/test_main_dbus.cpp
index 44809741a..329c61358 100644
--- a/tests/test_main_dbus.cpp
+++ b/tests/test_main_dbus.cpp
@@ -2,6 +2,7 @@
#include <gio/gio.h>
#include <NuxCore/Logger.h>
#include <Nux/Nux.h>
+#include <UnityCore/GLibDBusNameWatcher.h>
#include "test_utils.h"
#include "config.h"
@@ -35,7 +36,7 @@ int main(int argc, char** argv)
g_print ("option parsing failed: %s\n", error->message);
return 1;
}
-
+
signal(SIGINT, signal_handler);
nux::NuxInitialize (0);
@@ -66,24 +67,12 @@ int main(int argc, char** argv)
static bool wait_until_test_service_appears()
{
bool have_name = false;
+ unity::glib::DBusNameWatcher watcher("com.canonical.Unity.Test");
+ watcher.appeared.connect([&have_name] (std::string const&, std::string const&) {
+ have_name = true;
+ });
- auto callback = [](GDBusConnection * conn,
- const char * name,
- const char * name_owner,
- gpointer user_data)
- {
- *(bool*)user_data = true;
- };
-
- g_bus_watch_name(G_BUS_TYPE_SESSION,
- "com.canonical.Unity.Test",
- G_BUS_NAME_WATCHER_FLAGS_NONE,
- callback,
- NULL,
- &have_name,
- NULL);
-
- Utils::WaitUntil(have_name, 3);
+ Utils::WaitUntil(have_name, 3, "Service has not appeared");
EXPECT_TRUE(have_name);
return have_name;
@@ -92,6 +81,12 @@ static bool wait_until_test_service_appears()
static void tell_service_to_exit()
{
// Ask the service to exit
+ bool lost_name = false;
+ unity::glib::DBusNameWatcher watcher("com.canonical.Unity.Test");
+ watcher.vanished.connect([&lost_name] (std::string const&) {
+ lost_name = true;
+ });
+
GDBusConnection* connection = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL);
g_dbus_connection_call_sync(connection,
"com.canonical.Unity.Test",
@@ -104,6 +99,9 @@ static void tell_service_to_exit()
-1,
NULL, NULL);
g_object_unref(connection);
+
+ Utils::WaitUntil(lost_name, 3, "Service is not vanished");
+ EXPECT_TRUE(lost_name);
}
static void signal_handler(int sig)
diff --git a/tests/test_result_renderer.cpp b/tests/test_result_renderer.cpp
index 7a99d6c6c..8542b7d79 100644
--- a/tests/test_result_renderer.cpp
+++ b/tests/test_result_renderer.cpp
@@ -79,7 +79,7 @@ public:
}
private:
- std::auto_ptr<dash::TextureContainer> renderer_;
+ std::unique_ptr<dash::TextureContainer> renderer_;
};
TEST_F(TestResultRenderer, TestConstruction)
diff --git a/tests/test_service_panel.cpp b/tests/test_service_panel.cpp
index ef8d70404..88c4f45dd 100644
--- a/tests/test_service_panel.cpp
+++ b/tests/test_service_panel.cpp
@@ -17,6 +17,10 @@ static const char * panel_interface =
" <arg type='" ENTRY_ARRAY_SIGNATURE "' name='state' direction='out'/>"
" </method>"
"\n"
+" <method name='GetIconPaths'>"
+" <arg type='as' name='paths' direction='out'/>"
+" </method>"
+"\n"
" <signal name='ReSync'>"
" <arg type='s' name='indicator_id' />"
" </signal>"
@@ -118,6 +122,10 @@ GVariant* Panel::OnMethodCall(std::string const& method, GVariant *parameters)
{
return g_variant_new("(b)", trigger_resync1_sent_ ? TRUE : FALSE);
}
+ else if (method == "GetIconPaths")
+ {
+ return g_variant_new("(as)", nullptr);
+ }
return nullptr;
}
diff --git a/tests/test_showdesktop_handler.cpp b/tests/test_showdesktop_handler.cpp
index 8b4566cd8..b7831754e 100644
--- a/tests/test_showdesktop_handler.cpp
+++ b/tests/test_showdesktop_handler.cpp
@@ -3,6 +3,7 @@
#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include <UnityShowdesktopHandler.h>
+#include "test_utils.h"
using namespace unity;
using ::testing::_;
@@ -404,7 +405,7 @@ TEST_F(UnityShowdesktopHandlerTest, TestAnimationPostPaintActions)
EXPECT_EQ (ShowdesktopHandler::animating_windows.size (), 1);
}
-TEST_F(UnityShowdesktopHandlerTest, DISABLED_TestAnimationOpacity)
+TEST_F(UnityShowdesktopHandlerTest, UNSTABLE_TEST(TestAnimationOpacity))
{
MockUnityShowdesktopHandlerWindow mMockWindow;
diff --git a/tests/test_utils.h b/tests/test_utils.h
index 4b04d8be4..4e7ecaed1 100644
--- a/tests/test_utils.h
+++ b/tests/test_utils.h
@@ -8,6 +8,16 @@
#include "GLibWrapper.h"
#include "config.h"
+#ifdef UNITY_DEBUG_BUILD
+#define UNSTABLE_PREFIX UNSTABLE
+#else
+#define UNSTABLE_PREFIX DISABLED
+#endif
+
+#define TEST_PREFIX(prefix,test) prefix ## _ ## test
+#define TEST_EVALUATOR(prefix,test) TEST_PREFIX(prefix,test)
+#define UNSTABLE_TEST(test) TEST_EVALUATOR(UNSTABLE_PREFIX, test)
+
namespace
{
diff --git a/tests/test_xdnd_start_stop_notifier_imp.cpp b/tests/test_xdnd_start_stop_notifier_imp.cpp
index 621010447..9811664ee 100644
--- a/tests/test_xdnd_start_stop_notifier_imp.cpp
+++ b/tests/test_xdnd_start_stop_notifier_imp.cpp
@@ -47,7 +47,7 @@ struct TestXdndStartStopNotifierImp : public Test {
unity::XdndStartStopNotifierImp xdnd_start_stop_notifier;
};
-TEST_F(TestXdndStartStopNotifierImp, DISABLED_SignalStarted)
+TEST_F(TestXdndStartStopNotifierImp, UNSTABLE_TEST(SignalStarted))
{
bool signal_received = false;
xdnd_start_stop_notifier.started.connect([&](){
@@ -63,7 +63,7 @@ TEST_F(TestXdndStartStopNotifierImp, DISABLED_SignalStarted)
//XTestFakeButtonEvent(display_, 1, False, CurrentTime);
}
-TEST_F(TestXdndStartStopNotifierImp, DISABLED_SignalFinished)
+TEST_F(TestXdndStartStopNotifierImp, UNSTABLE_TEST(SignalFinished))
{
bool signal_received = false;
xdnd_start_stop_notifier.finished.connect([&](){
diff --git a/unity-shared/GnomeKeyGrabber.cpp b/unity-shared/GnomeKeyGrabber.cpp
index 0d0cdd5d7..88d49871a 100644
--- a/unity-shared/GnomeKeyGrabber.cpp
+++ b/unity-shared/GnomeKeyGrabber.cpp
@@ -1,6 +1,6 @@
// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
/*
- * Copyright (C) 2013 Canonical Ltd
+ * Copyright (C) 2013-2015 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
@@ -15,6 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Authored by: William Hua <william.hua@canonical.com>
+ * Marco Trevisan <marco.trevisan@canonical.com>
*/
#include "GnomeKeyGrabberImpl.h"
@@ -63,168 +64,174 @@ namespace testing
std::string const DBUS_NAME = "com.canonical.Unity.Test.GnomeKeyGrabber";
}
+namespace
+{
+inline int compiz_event_timestamp(CompOption::Vector& options) { return options[7].value().i(); }
+}
+
GnomeGrabber::Impl::Impl(bool test_mode)
- : shell_server_(test_mode ? testing::DBUS_NAME : shell::DBUS_NAME)
- , screen_(screen)
+ : screen_(screen)
+ , shell_server_(test_mode ? testing::DBUS_NAME : shell::DBUS_NAME)
, current_action_id_(0)
{
shell_server_.AddObjects(shell::INTROSPECTION_XML, shell::DBUS_OBJECT_PATH);
shell_object_ = shell_server_.GetObject(shell::DBUS_INTERFACE);
- shell_object_->SetMethodsCallsHandler(sigc::mem_fun(this, &Impl::onShellMethodCall));
+ shell_object_->SetMethodsCallsHandlerFull(sigc::mem_fun(this, &Impl::OnShellMethodCall));
}
GnomeGrabber::Impl::~Impl()
{
- if (screen_)
- {
- for (auto& action : actions_)
- screen_->removeAction(&action);
- }
+ for (auto& action : actions_)
+ screen_->removeAction(&action);
}
-unsigned int GnomeGrabber::Impl::addAction(CompAction const& action, bool addressable)
+uint32_t GnomeGrabber::Impl::NextActionID()
{
- ++current_action_id_;
- actions_.push_back(action);
- action_ids_.push_back(current_action_id_);
+ return ++current_action_id_;
+}
+
+bool GnomeGrabber::Impl::AddAction(CompAction const& action, uint32_t& action_id)
+{
+ LOG_DEBUG(logger) << "AddAction (\"" << action.keyToString() << "\") = " << action_id;
- if (addressable)
+ if (action.key().toString().empty())
{
- action_ids_by_action_[&action] = current_action_id_;
- actions_by_action_id_[current_action_id_] = &action;
+ LOG_WARN(logger) << "Trying to grab a disabled action, we skip it";
+ return false;
}
- if (screen_)
- screen_->addAction(&actions_.back());
+ auto it = std::find(actions_.begin(), actions_.end(), action);
+ if (it != actions_.end())
+ {
+ action_id = actions_ids_[it - actions_.begin()];
+ LOG_DEBUG(logger) << "Key binding \"" << action.keyToString() << "\" is already grabbed, reusing id " << action_id;
+ return true;
+ }
- LOG_DEBUG(logger) << "addAction (\"" << action.keyToString() << "\", " << addressable << ") = " << current_action_id_;
+ if (screen_->addAction(const_cast<CompAction*>(&action)))
+ {
+ actions_ids_.push_back(action_id);
+ actions_.push_back(action);
+ return true;
+ }
- return current_action_id_;
+ LOG_ERROR(logger) << "Impossible to grab action \"" << action.keyToString() << "\"";
+ return false;
}
-bool GnomeGrabber::Impl::removeAction(CompAction const& action)
+uint32_t GnomeGrabber::Impl::AddAction(CompAction const& action)
{
- auto i = action_ids_by_action_.find(&action);
- return i != action_ids_by_action_.end() && removeAction(i->second);
+ auto action_id = NextActionID();
+ return AddAction(action, action_id) ? action_id : 0;
}
-bool GnomeGrabber::Impl::removeAction(unsigned int action_id)
+bool GnomeGrabber::Impl::RemoveAction(CompAction const& action)
{
- auto i = std::find(action_ids_.begin(), action_ids_.end(), action_id);
+ auto it = std::find(actions_.begin(), actions_.end(), action);
- if (i != action_ids_.end())
- {
- auto j = actions_.begin() + (i - action_ids_.begin());
- auto k = actions_by_action_id_.find(action_id);
+ if (it != actions_.end())
+ return RemoveActionByIndex(it - actions_.begin());
- LOG_DEBUG(logger) << "removeAction (" << action_id << " \"" << j->keyToString() << "\")";
+ return false;
+}
- if (screen_)
- screen_->removeAction(&(*j));
+bool GnomeGrabber::Impl::RemoveActionByID(uint32_t action_id)
+{
+ if (!action_id)
+ return false;
- if (k != actions_by_action_id_.end())
- {
- action_ids_by_action_.erase(k->second);
- actions_by_action_id_.erase(k);
- }
+ auto it = std::find(actions_ids_.begin(), actions_ids_.end(), action_id);
- action_ids_.erase(i);
- actions_.erase(j);
- return true;
- }
+ if (it != actions_ids_.end())
+ return RemoveActionByIndex(it - actions_ids_.begin());
return false;
}
-GVariant* GnomeGrabber::Impl::onShellMethodCall(std::string const& method, GVariant* parameters)
+bool GnomeGrabber::Impl::RemoveActionByIndex(size_t index)
+{
+ if (!index || index >= actions_.size())
+ return false;
+
+ CompAction* action = &(actions_[index]);
+ LOG_DEBUG(logger) << "RemoveAction (\"" << action->keyToString() << "\")";
+
+ screen_->removeAction(action);
+ actions_.erase(actions_.begin() + index);
+ actions_ids_.erase(actions_ids_.begin() + index);
+
+ return true;
+}
+
+GVariant* GnomeGrabber::Impl::OnShellMethodCall(std::string const& method, GVariant* parameters, std::string const& sender, std::string const&)
{
LOG_DEBUG(logger) << "Called method '" << method << "'";
if (method == "GrabAccelerators")
{
- if (g_variant_is_of_type(parameters, G_VARIANT_TYPE("(a(su))")))
- {
- GVariant* variant;
- GVariantBuilder builder;
- GVariantIter* iterator;
- gchar const* accelerator;
- guint flags;
+ GVariant* variant;
+ GVariantBuilder builder;
+ GVariantIter* iterator;
+ gchar const* accelerator;
+ guint flags;
- g_variant_builder_init(&builder, G_VARIANT_TYPE("au"));
- g_variant_get(parameters, "(a(su))", &iterator);
+ g_variant_builder_init(&builder, G_VARIANT_TYPE("au"));
+ g_variant_get(parameters, "(a(su))", &iterator);
- while (g_variant_iter_next(iterator, "(&su)", &accelerator, &flags))
- g_variant_builder_add(&builder, "u", grabAccelerator(accelerator, flags));
+ while (g_variant_iter_next(iterator, "(&su)", &accelerator, &flags))
+ g_variant_builder_add(&builder, "u", GrabDBusAccelerator(sender, accelerator, flags));
- g_variant_iter_free(iterator);
- variant = g_variant_builder_end(&builder);
- return g_variant_new_tuple(&variant, 1);
- }
- else
- LOG_WARN(logger) << "Expected arguments of type (a(su))";
+ g_variant_iter_free(iterator);
+ variant = g_variant_builder_end(&builder);
+ return g_variant_new_tuple(&variant, 1);
}
else if (method == "GrabAccelerator")
{
- if (g_variant_is_of_type(parameters, G_VARIANT_TYPE("(su)")))
- {
- GVariant* variant;
- gchar const* accelerator;
- guint flags;
+ gchar const* accelerator;
+ guint flags;
+ g_variant_get(parameters, "(&su)", &accelerator, &flags);
- g_variant_get(parameters, "(&su)", &accelerator, &flags);
- variant = g_variant_new_uint32(grabAccelerator(accelerator, flags));
- return g_variant_new_tuple(&variant, 1);
- }
- else
- LOG_WARN(logger) << "Expected arguments of type (su)";
+ if (uint32_t action_id = GrabDBusAccelerator(sender, accelerator, flags))
+ return g_variant_new("(u)", action_id);
}
else if (method == "UngrabAccelerator")
{
- if (g_variant_is_of_type(parameters, G_VARIANT_TYPE("(u)")))
- {
- GVariant* variant;
- guint action;
-
- g_variant_get(parameters, "(u)", &action);
- variant = g_variant_new_boolean(removeAction(action));
- return g_variant_new_tuple(&variant, 1);
- }
- else
- LOG_WARN(logger) << "Expected arguments of type (u)";
+ uint32_t action_id;
+ g_variant_get(parameters, "(u)", &action_id);
+ return g_variant_new("(b)", UnGrabDBusAccelerator(sender, action_id));
}
return nullptr;
}
-unsigned int GnomeGrabber::Impl::grabAccelerator(char const* accelerator, unsigned int flags)
+uint32_t GnomeGrabber::Impl::GrabDBusAccelerator(std::string const& owner, std::string const& accelerator, uint32_t flags)
{
CompAction action;
action.keyFromString(accelerator);
+ uint32_t action_id = NextActionID();
+
+ LOG_DEBUG(logger) << "GrabDBusAccelerator \"" << accelerator << "\"";
if (action.key().toString().empty())
{
- CompString prefixed = "XF86" + CompString(accelerator);
+ auto prefixed = "XF86" + accelerator;
LOG_DEBUG(logger) << "Can't grab \"" << accelerator << "\", trying \"" << prefixed << "\"";
action.keyFromString(prefixed);
}
- else
- {
- LOG_DEBUG(logger) << "grabAccelerator \"" << accelerator << "\"";
- }
- if (!isActionPostponed(action))
+ if (!IsActionPostponed(action))
{
action.setState(CompAction::StateInitKey);
- action.setInitiate([this](CompAction* action, CompAction::State state, CompOption::Vector& options) {
+ action.setInitiate([this, action_id](CompAction* action, CompAction::State state, CompOption::Vector& options) {
LOG_DEBUG(logger) << "pressed \"" << action->keyToString() << "\"";
- activateAction(action, 0, options[7].value().i());
+ ActivateDBusAction(*action, action_id, 0, compiz_event_timestamp(options));
return true;
});
}
else
{
action.setState(CompAction::StateInitKey | CompAction::StateTermKey);
- action.setTerminate([this](CompAction* action, CompAction::State state, CompOption::Vector& options) {
+ action.setTerminate([this, action_id](CompAction* action, CompAction::State state, CompOption::Vector& options) {
auto key = action->keyToString();
LOG_DEBUG(logger) << "released \"" << key << "\"";
@@ -232,7 +239,7 @@ unsigned int GnomeGrabber::Impl::grabAccelerator(char const* accelerator, unsign
if (state & CompAction::StateTermTapped)
{
LOG_DEBUG(logger) << "tapped \"" << key << "\"";
- activateAction(action, 0, options[7].value().i());
+ ActivateDBusAction(*action, action_id, 0, compiz_event_timestamp(options));
return true;
}
@@ -240,22 +247,86 @@ unsigned int GnomeGrabber::Impl::grabAccelerator(char const* accelerator, unsign
});
}
- return addAction(action, false);
+ if (AddAction(action, action_id))
+ {
+ auto& owner_actions = actions_by_owner_[owner];
+ bool first_insertion = owner_actions.actions.empty();
+ owner_actions.actions.insert(action_id);
+
+ if (first_insertion)
+ {
+ LOG_DEBUG(logger) << "Initialize dbus watcher for owner '" << owner << "'";
+ owner_actions.watcher = std::make_shared<glib::DBusNameWatcher>(owner);
+ owner_actions.watcher->vanished.connect([this] (std::string const& name) {
+ LOG_DEBUG(logger) << "Signal destination vanished '" << name << "', removing related actions";
+ auto it = actions_by_owner_.find(name);
+ if (it != actions_by_owner_.end())
+ {
+ for (auto action_id : it->second.actions)
+ RemoveActionForOwner(action_id, name);
+
+ actions_by_owner_.erase(it);
+ }
+ });
+ }
+
+ return action_id;
+ }
+
+ return 0;
}
-void GnomeGrabber::Impl::activateAction(CompAction const* action, unsigned device, unsigned timestamp) const
+bool GnomeGrabber::Impl::UnGrabDBusAccelerator(std::string const& owner, uint32_t action_id)
{
- ptrdiff_t i = action - &actions_.front();
+ LOG_DEBUG(logger) << "UnGrabDBusAccelerator \"" << action_id << "\"";
- if (0 <= i && i < static_cast<ptrdiff_t>(action_ids_.size()))
+ auto it = actions_by_owner_.find(owner);
+ if (it != actions_by_owner_.end())
{
- auto action_id = action_ids_[i];
- LOG_DEBUG(logger) << "activateAction (" << action_id << " \"" << action->keyToString() << "\")";
- shell_object_->EmitSignal("AcceleratorActivated", g_variant_new("(uuu)", action_id, device, timestamp));
+ auto& actions = it->second.actions;
+ actions.erase(action_id);
+
+ if (actions.empty())
+ actions_by_owner_.erase(it);
+
+ return RemoveActionForOwner(action_id, owner);
}
+
+ LOG_WARN(logger) << "Action " << action_id << " was not registered by " << owner << ". "
+ << "Unregistration denied";
+ return false;
}
-bool GnomeGrabber::Impl::isActionPostponed(CompAction const& action) const
+bool GnomeGrabber::Impl::RemoveActionForOwner(uint32_t action_id, std::string const& owner)
+{
+ for (auto it = actions_by_owner_.begin(); it != actions_by_owner_.end(); ++it)
+ {
+ if (it->first == owner)
+ continue;
+
+ auto const& actions = it->second.actions;
+ if (actions.find(action_id) != actions.end())
+ {
+ LOG_DEBUG(logger) << "Action " << action_id << " registered for multiple destinations, not removed";
+ return false;
+ }
+ }
+
+ return RemoveActionByID(action_id);
+}
+
+void GnomeGrabber::Impl::ActivateDBusAction(CompAction const& action, uint32_t action_id, uint32_t device, uint32_t timestamp) const
+{
+ LOG_DEBUG(logger) << "ActivateAction (" << action_id << " \"" << action.keyToString() << "\")";
+
+ for (auto const& pair : actions_by_owner_)
+ {
+ if (pair.second.actions.find(action_id) != pair.second.actions.end())
+ shell_object_->EmitSignal("AcceleratorActivated", g_variant_new("(uuu)", action_id, device, timestamp), pair.first);
+ }
+}
+
+bool GnomeGrabber::Impl::IsActionPostponed(CompAction const& action) const
{
int keycode = action.key().keycode();
return keycode == 0 || modHandler->keycodeToModifiers(keycode) != 0;
@@ -279,14 +350,19 @@ CompAction::Vector& GnomeGrabber::GetActions()
return impl_->actions_;
}
-void GnomeGrabber::AddAction(CompAction const& action)
+uint32_t GnomeGrabber::AddAction(CompAction const& action)
+{
+ return impl_->AddAction(action);
+}
+
+bool GnomeGrabber::RemoveAction(CompAction const& action)
{
- impl_->addAction(action);
+ return impl_->RemoveAction(action);
}
-void GnomeGrabber::RemoveAction(CompAction const& action)
+bool GnomeGrabber::RemoveAction(uint32_t action_id)
{
- impl_->removeAction(action);
+ return impl_->RemoveActionByID(action_id);
}
} // namespace key
diff --git a/unity-shared/GnomeKeyGrabber.h b/unity-shared/GnomeKeyGrabber.h
index cae4e610c..284b20ab1 100644
--- a/unity-shared/GnomeKeyGrabber.h
+++ b/unity-shared/GnomeKeyGrabber.h
@@ -32,9 +32,11 @@ public:
GnomeGrabber();
virtual ~GnomeGrabber();
- void AddAction(CompAction const&);
- void RemoveAction(CompAction const&);
- CompAction::Vector& GetActions();
+ uint32_t AddAction(CompAction const&) override;
+ bool RemoveAction(CompAction const&) override;
+ bool RemoveAction(uint32_t action_id) override;
+
+ CompAction::Vector& GetActions() override;
protected:
struct TestMode {};
diff --git a/unity-shared/GnomeKeyGrabberImpl.h b/unity-shared/GnomeKeyGrabberImpl.h
index 585d761fa..2c03827dd 100644
--- a/unity-shared/GnomeKeyGrabberImpl.h
+++ b/unity-shared/GnomeKeyGrabberImpl.h
@@ -1,21 +1,22 @@
// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
/*
-* Copyright (C) 2013 Canonical Ltd
-*
-* This program is free software: you can redistribute it and/or modify
-* it under the terms of the GNU General Public License version 3 as
-* published by the Free Software Foundation.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with this program. If not, see <http://www.gnu.org/licenses/>.
-*
-* Authored by: William Hua <william.hua@canonical.com>
-*/
+ * Copyright (C) 2013-2015 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: William Hua <william.hua@canonical.com>
+ * Marco Trevisan <marco.trevisan@canonical.com>
+ */
#ifndef __GNOME_KEY_GRABBER_IMPL_H__
#define __GNOME_KEY_GRABBER_IMPL_H__
@@ -23,8 +24,10 @@
#include "GnomeKeyGrabber.h"
#include <unordered_map>
+#include <unordered_set>
#include <UnityCore/GLibDBusProxy.h>
#include <UnityCore/GLibDBusServer.h>
+#include <UnityCore/GLibDBusNameWatcher.h>
namespace unity
{
@@ -36,26 +39,34 @@ struct GnomeGrabber::Impl
Impl(bool test_mode = false);
~Impl();
- glib::DBusServer shell_server_;
- glib::DBusObject::Ptr shell_object_;
+ uint32_t NextActionID();
- CompScreen* screen_;
- CompAction::Vector actions_;
- std::vector<unsigned int> action_ids_;
- unsigned int current_action_id_;
+ bool AddAction(CompAction const& action, uint32_t& action_id);
+ uint32_t AddAction(CompAction const& action);
+
+ bool RemoveAction(CompAction const& action);
+ bool RemoveActionByID(uint32_t action_id);
+ bool RemoveActionByIndex(size_t index);
- std::unordered_map<CompAction const*, unsigned int> action_ids_by_action_;
- std::unordered_map<unsigned int, CompAction const*> actions_by_action_id_;
+ GVariant* OnShellMethodCall(std::string const& method, GVariant* parameters, std::string const& sender, std::string const&);
+ uint32_t GrabDBusAccelerator(std::string const& owner, std::string const& accelerator, uint32_t flags);
+ bool UnGrabDBusAccelerator(std::string const& sender, uint32_t action_id);
+ void ActivateDBusAction(CompAction const& action, uint32_t id, uint32_t device, uint32_t timestamp) const;
+ bool RemoveActionForOwner(uint32_t action_id, std::string const& owner);
- unsigned int addAction(CompAction const& action, bool addressable = true);
- bool removeAction(CompAction const& action);
- bool removeAction(unsigned int action_id);
+ bool IsActionPostponed(CompAction const& action) const;
- GVariant* onShellMethodCall(std::string const& method, GVariant* parameters);
- unsigned int grabAccelerator(char const* accelerator, unsigned int flags);
- void activateAction(CompAction const* action, unsigned device, unsigned timestamp) const;
+ CompScreen* screen_;
+
+ glib::DBusServer shell_server_;
+ glib::DBusObject::Ptr shell_object_;
+
+ uint32_t current_action_id_;
+ std::vector<uint32_t> actions_ids_;
+ CompAction::Vector actions_;
- bool isActionPostponed(CompAction const& action) const;
+ struct OwnerActions { glib::DBusNameWatcher::Ptr watcher; std::unordered_set<uint32_t> actions; };
+ std::unordered_map<std::string, OwnerActions> actions_by_owner_;
};
} // namespace key
diff --git a/unity-shared/KeyGrabber.h b/unity-shared/KeyGrabber.h
index 895090a20..0688a9c4f 100644
--- a/unity-shared/KeyGrabber.h
+++ b/unity-shared/KeyGrabber.h
@@ -32,8 +32,10 @@ public:
typedef std::shared_ptr<Grabber> Ptr;
virtual ~Grabber() = default;
- virtual void AddAction(CompAction const&) = 0;
- virtual void RemoveAction(CompAction const&) = 0;
+ virtual uint32_t AddAction(CompAction const&) = 0;
+ virtual bool RemoveAction(CompAction const&) = 0;
+ virtual bool RemoveAction(uint32_t id) = 0;
+
virtual CompAction::Vector& GetActions() = 0;
};
diff --git a/unity-shared/MenuManager.cpp b/unity-shared/MenuManager.cpp
index 4aef7cba7..f00887ce8 100644
--- a/unity-shared/MenuManager.cpp
+++ b/unity-shared/MenuManager.cpp
@@ -142,18 +142,18 @@ struct Manager::Impl : sigc::trackable
{
auto key = gdk_keyval_to_lower(gdk_unicode_to_keyval(mnemonic));
glib::String accelerator(gtk_accelerator_name(key, GDK_MOD1_MASK));
- auto action = std::make_shared<CompAction>();
auto const& id = entry->id();
- action->keyFromString(accelerator);
- action->setState(CompAction::StateInitKey);
- action->setInitiate([this, id] (CompAction* action, CompAction::State, CompOption::Vector&) {
+ CompAction action;
+ action.keyFromString(accelerator);
+ action.setState(CompAction::StateInitKey);
+ action.setInitiate([this, id] (CompAction* action, CompAction::State, CompOption::Vector&) {
LOG_DEBUG(logger) << "pressed \"" << action->keyToString() << "\"";
return parent_->key_activate_entry.emit(id);
});
- entry_actions_.insert({entry, action});
- key_grabber_->AddAction(*action);
+ if (uint32_t action_id = key_grabber_->AddAction(action))
+ entry_actions_.insert({entry, action_id});
}
}
@@ -163,7 +163,7 @@ struct Manager::Impl : sigc::trackable
if (it != entry_actions_.end())
{
- key_grabber_->RemoveAction(*it->second);
+ key_grabber_->RemoveAction(it->second);
entry_actions_.erase(it);
}
}
@@ -172,7 +172,7 @@ struct Manager::Impl : sigc::trackable
{
for (auto it = entry_actions_.begin(); it != entry_actions_.end();)
{
- key_grabber_->RemoveAction(*it->second);
+ key_grabber_->RemoveAction(it->second);
it = entry_actions_.erase(it);
}
}
@@ -240,7 +240,7 @@ struct Manager::Impl : sigc::trackable
connection::Wrapper active_win_conn_;
glib::Object<GSettings> settings_;
glib::SignalManager signals_;
- std::unordered_map<indicator::Entry::Ptr, std::shared_ptr<CompAction>> entry_actions_;
+ std::unordered_map<indicator::Entry::Ptr, uint32_t> entry_actions_;
};
Manager::Manager(Indicators::Ptr const& indicators, key::Grabber::Ptr const& grabber)
diff --git a/unity-standalone/StandaloneUnity.cpp b/unity-standalone/StandaloneUnity.cpp
index 4ae5d45de..6a0af61b6 100644
--- a/unity-standalone/StandaloneUnity.cpp
+++ b/unity-standalone/StandaloneUnity.cpp
@@ -72,12 +72,10 @@ struct StandaloneDndManager : XdndManager
struct StandaloneKeyGrabber : key::Grabber
{
- CompAction::Vector& GetActions() { return actions_; }
- void AddAction(CompAction const&) {}
- void RemoveAction(CompAction const&) {}
-
- private:
- CompAction::Vector actions_;
+ CompAction::Vector& GetActions() override { return noActions(); }
+ uint32_t AddAction(CompAction const&) override { return 0; };
+ bool RemoveAction(CompAction const&) override { return false; };
+ bool RemoveAction(uint32_t id) override { return false; };
};
class UnityStandalone