diff options
| author | Marco Trevisan (Treviño) <mail@3v1n0.net> | 2015-10-02 14:02:05 +0000 |
|---|---|---|
| committer | CI Train Bot <ci-train-bot@canonical.com> | 2015-10-02 14:02:05 +0000 |
| commit | 9304ca7b15387572a39cc91542e3cc64fc851a19 (patch) | |
| tree | f9792a40f98f6d6b7542f06d5ccf71a17afa72a5 | |
| parent | b8f8a52649fca093b357278a7b61ebcc99385e4a (diff) | |
| parent | 9239a7575eec66b6750565550e2171b815abd4be (diff) | |
GnomeKeyGrabber: Don't allow an action to be grabbed multiple times
And always return the same action id for a specific key binding. Fixes: #1459571 Approved by: Andrea Azzarone (bzr r4018)
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 |
