summaryrefslogtreecommitdiff
path: root/plugins/unityshell
diff options
authorWilliam Hua <william.hua@canonical.com>2013-12-12 16:15:26 -0500
committerWilliam Hua <william.hua@canonical.com>2013-12-12 16:15:26 -0500
commit6b469bfab3a36ccf028a60d556b1d0c5f5279d4d (patch)
tree05bfa69d001023fed321e3e37f5eda906649e52e /plugins/unityshell
parente46aad4201b5dec526092b355cddf032903785e8 (diff)
GnomeKeyGrabber initial implementation.
(bzr r3608.4.1)
Diffstat (limited to 'plugins/unityshell')
-rw-r--r--plugins/unityshell/src/GnomeKeyGrabber.cpp274
-rw-r--r--plugins/unityshell/src/GnomeKeyGrabber.h56
-rw-r--r--plugins/unityshell/src/GnomeKeyGrabberImpl.h64
-rw-r--r--plugins/unityshell/src/unityshell.cpp6
-rw-r--r--plugins/unityshell/src/unityshell.h7
5 files changed, 407 insertions, 0 deletions
diff --git a/plugins/unityshell/src/GnomeKeyGrabber.cpp b/plugins/unityshell/src/GnomeKeyGrabber.cpp
new file mode 100644
index 000000000..21a1d2517
--- /dev/null
+++ b/plugins/unityshell/src/GnomeKeyGrabber.cpp
@@ -0,0 +1,274 @@
+// -*- 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>
+*/
+
+#include "GnomeKeyGrabberImpl.h"
+
+#include <NuxCore/Logger.h>
+
+namespace unity
+{
+namespace grabber
+{
+DECLARE_LOGGER(logger, "unity.grabber.gnome");
+
+// Private implementation
+namespace shell
+{
+const std::string DBUS_NAME = "org.gnome.Shell";
+const std::string DBUS_INTERFACE = "org.gnome.Shell";
+const std::string DBUS_OBJECT_PATH = "/org/gnome/Shell";
+const std::string INTROSPECTION_XML =
+R"(<node>
+ <interface name='org.gnome.Shell'>
+ <method name='GrabAccelerators'>
+ <arg type='a(su)' direction='in' name='accelerators'/>
+ <arg type='au' direction='out' name='actions'/>
+ </method>
+ <method name='GrabAccelerator'>
+ <arg type='s' direction='in' name='accelerator'/>
+ <arg type='u' direction='in' name='flags'/>
+ <arg type='u' direction='out' name='action'/>
+ </method>
+ <method name='UngrabAccelerator'>
+ <arg type='u' direction='in' name='action'/>
+ <arg type='b' direction='out' name='success'/>
+ </method>
+ <signal name='AcceleratorActivated'>
+ <arg type='u' name='action'/>
+ <arg type='u' name='device'/>
+ </signal>
+ </interface>
+</node>)";
+}
+
+namespace testing
+{
+const std::string DBUS_NAME = "com.canonical.Unity.Test.GnomeKeyGrabber";
+}
+
+GnomeKeyGrabber::Impl::Impl(GnomeKeyGrabber* grabber, CompScreen* screen, bool test_mode)
+ : grabber_(grabber)
+ , shell_server_(test_mode ? testing::DBUS_NAME : shell::DBUS_NAME)
+ , screen_(screen)
+ , current_action_id_(0)
+ , test_mode_(test_mode)
+{
+ 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));
+}
+
+GnomeKeyGrabber::Impl::~Impl()
+{
+}
+
+unsigned int GnomeKeyGrabber::Impl::addAction(const CompAction& action)
+{
+ current_action_id_++;
+ actions_.push_back(action);
+ action_for_id_[current_action_id_] = &actions_.back();
+ screen_->addAction(&actions_.back());
+ return current_action_id_;
+}
+
+bool GnomeKeyGrabber::Impl::removeAction(const CompAction& action)
+{
+ bool removed(false);
+
+ std::list<unsigned int> action_ids;
+
+ for (std::map<unsigned int, CompAction*>::const_iterator i(action_for_id_.begin()); i != action_for_id_.end(); ++i)
+ if (*i->second == action)
+ action_ids.push_front(i->first);
+
+ for (std::list<unsigned int>::const_iterator i(action_ids.begin()); i != action_ids.end(); ++i)
+ removed = removeAction(*i) || removed;
+
+ return removed;
+}
+
+bool GnomeKeyGrabber::Impl::removeAction(unsigned int action_id)
+{
+ std::map<unsigned int, CompAction*>::iterator i(action_for_id_.find(action_id));
+
+ if (i != action_for_id_.end())
+ {
+ CompAction* action = i->second;
+
+ screen_->removeAction(action);
+ action_for_id_.erase(i);
+
+ for (CompAction::Vector::iterator j(actions_.begin()); j != actions_.end(); ++j)
+ {
+ if (&*j == action) {
+ actions_.erase(j);
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+GVariant* GnomeKeyGrabber::Impl::onShellMethodCall(std::string const& method, GVariant* parameters)
+{
+ 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;
+ const gchar* accelerator;
+ guint flags;
+
+ 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));
+
+ 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))";
+ }
+ else if (method == "GrabAccelerator")
+ {
+ if (g_variant_is_of_type(parameters, G_VARIANT_TYPE("(su)")))
+ {
+ GVariant* variant;
+ const gchar* accelerator;
+ guint 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)";
+ }
+ 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)";
+ }
+
+ return nullptr;
+}
+
+unsigned int GnomeKeyGrabber::Impl::grabAccelerator(const char *accelerator, unsigned int flags)
+{
+ /* XXX: What is flags? */
+
+ CompAction action;
+ action.keyFromString(accelerator);
+ action.setInitiate(boost::bind(&GnomeKeyGrabber::Impl::actionInitiated, this, _1, _2, _3));
+ action.setTerminate(boost::bind(&GnomeKeyGrabber::Impl::actionTerminated, this, _1, _2, _3));
+ return addAction(action);
+}
+
+void GnomeKeyGrabber::Impl::activateAction(const CompAction* action, unsigned int device)
+{
+ unsigned int action_id(-1);
+ unsigned int closest_action_id(-1);
+
+ for (std::map<unsigned int, CompAction*>::const_iterator i(action_for_id_.begin()); i != action_for_id_.end(); ++i)
+ {
+ if (i->second == action)
+ {
+ action_id = i->first;
+ break;
+ }
+
+ if (*i->second == *action && (closest_action_id < 0 || i->first < closest_action_id))
+ closest_action_id = i->first;
+ }
+
+ if (action_id < 0)
+ action_id = closest_action_id;
+
+ if (action_id < 0)
+ return;
+
+ shell_object_->EmitSignal("AcceleratorActivated", g_variant_new("(uu)", action_id, device));
+}
+
+bool GnomeKeyGrabber::Impl::actionInitiated(CompAction* action, CompAction::State state, CompOption::Vector& options)
+{
+ /* XXX: Do this only once per initiate/terminate pair. */
+
+ activateAction(action, 0);
+ return true;
+}
+
+bool GnomeKeyGrabber::Impl::actionTerminated(CompAction* action, CompAction::State state, CompOption::Vector& options)
+{
+ /* XXX: Do this only once per initiate/terminate pair. */
+
+ activateAction(action, 1);
+ return true;
+}
+
+// Public implementation
+
+GnomeKeyGrabber::GnomeKeyGrabber(CompScreen* screen)
+ : impl_(new GnomeKeyGrabber::Impl(this, screen))
+{
+}
+
+GnomeKeyGrabber::GnomeKeyGrabber(CompScreen* screen, GnomeKeyGrabber::TestMode const& tm)
+ : impl_(new GnomeKeyGrabber::Impl(this, screen, true))
+{
+}
+
+GnomeKeyGrabber::~GnomeKeyGrabber()
+{
+}
+
+CompAction::Vector& GnomeKeyGrabber::getActions()
+{
+ return impl_->actions_;
+}
+
+void GnomeKeyGrabber::addAction(const CompAction& action)
+{
+ impl_->addAction(action);
+}
+
+void GnomeKeyGrabber::removeAction(const CompAction& action)
+{
+ impl_->removeAction(action);
+}
+
+} // namespace grabber
+} // namespace unity
diff --git a/plugins/unityshell/src/GnomeKeyGrabber.h b/plugins/unityshell/src/GnomeKeyGrabber.h
new file mode 100644
index 000000000..a91771c59
--- /dev/null
+++ b/plugins/unityshell/src/GnomeKeyGrabber.h
@@ -0,0 +1,56 @@
+// -*- 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>
+*/
+
+#ifndef __GNOME_KEY_GRABBER_H__
+#define __GNOME_KEY_GRABBER_H__
+
+#include <core/core.h>
+
+namespace unity
+{
+namespace grabber
+{
+
+class GnomeKeyGrabber
+{
+public:
+
+ explicit GnomeKeyGrabber(CompScreen* screen);
+ ~GnomeKeyGrabber();
+
+ CompAction::Vector& getActions();
+ void addAction(const CompAction& action);
+ void removeAction(const CompAction& action);
+
+ struct Impl;
+
+protected:
+
+ struct TestMode {};
+ GnomeKeyGrabber(CompScreen* screen, TestMode const&);
+
+private:
+
+ std::unique_ptr<Impl> impl_;
+};
+
+} // namespace grabber
+} // namespace unity
+
+#endif // __GNOME_KEY_GRABBER_H__
diff --git a/plugins/unityshell/src/GnomeKeyGrabberImpl.h b/plugins/unityshell/src/GnomeKeyGrabberImpl.h
new file mode 100644
index 000000000..b70171686
--- /dev/null
+++ b/plugins/unityshell/src/GnomeKeyGrabberImpl.h
@@ -0,0 +1,64 @@
+// -*- 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>
+*/
+
+#ifndef __GNOME_KEY_GRABBER_IMPL_H__
+#define __GNOME_KEY_GRABBER_IMPL_H__
+
+#include "GnomeKeyGrabber.h"
+
+#include <UnityCore/GLibDBusProxy.h>
+#include <UnityCore/GLibDBusServer.h>
+
+namespace unity
+{
+namespace grabber
+{
+
+struct GnomeKeyGrabber::Impl
+{
+ Impl(GnomeKeyGrabber* parent, CompScreen* screen, bool test_mode = false);
+ ~Impl();
+
+ unsigned int addAction(const CompAction& action);
+ bool removeAction(const CompAction& action);
+ bool removeAction(unsigned int action_id);
+
+ GVariant* onShellMethodCall(std::string const& method, GVariant* parameters);
+ unsigned int grabAccelerator(const char *accelerator, unsigned int flags);
+ void activateAction(const CompAction* action, unsigned int device);
+
+ bool actionInitiated(CompAction* action, CompAction::State state, CompOption::Vector& options);
+ bool actionTerminated(CompAction* action, CompAction::State state, CompOption::Vector& options);
+
+ GnomeKeyGrabber* grabber_;
+ glib::DBusServer shell_server_;
+ glib::DBusObject::Ptr shell_object_;
+
+ CompScreen* screen_;
+ CompAction::Vector actions_;
+ unsigned int current_action_id_;
+ std::map<unsigned int, CompAction*> action_for_id_;
+
+ bool test_mode_;
+};
+
+} // namespace grabber
+} // namespace unity
+
+#endif // __GNOME_KEY_GRABBER_IMPL_H__
diff --git a/plugins/unityshell/src/unityshell.cpp b/plugins/unityshell/src/unityshell.cpp
index 8c6e229a6..e367baaa4 100644
--- a/plugins/unityshell/src/unityshell.cpp
+++ b/plugins/unityshell/src/unityshell.cpp
@@ -174,6 +174,7 @@ UnityScreen::UnityScreen(CompScreen* screen)
, dirty_helpers_on_this_frame_(false)
, back_buffer_age_(0)
, is_desktop_active_(false)
+ , grabber_(screen)
{
Timer timer;
#ifndef USE_GLES
@@ -3525,6 +3526,11 @@ void UnityScreen::InitGesturesSupport()
gestures_sub_windows_->Activate();
}
+CompAction::Vector& UnityScreen::getActions()
+{
+ return grabber_.getActions();
+}
+
/* Window init */
GLTexture::List UnityWindow::close_normal_tex_;
GLTexture::List UnityWindow::close_prelight_tex_;
diff --git a/plugins/unityshell/src/unityshell.h b/plugins/unityshell/src/unityshell.h
index 2aa5b72f5..4e6dc8a24 100644
--- a/plugins/unityshell/src/unityshell.h
+++ b/plugins/unityshell/src/unityshell.h
@@ -80,6 +80,8 @@
#include "unityshell_glow.h"
+#include "GnomeKeyGrabber.h"
+
namespace unity
{
class UnityWindow;
@@ -93,6 +95,7 @@ class UnityScreen :
public GLScreenInterface,
public BaseSwitchScreen,
public PluginClassHandler <UnityScreen, CompScreen>,
+ public CompAction::Class,
public UnityshellOptions
{
public:
@@ -209,6 +212,8 @@ public:
ui::LayoutWindow::Ptr GetSwitcherDetailLayoutWindow(Window window) const;
+ CompAction::Vector& getActions();
+
protected:
std::string GetName() const;
void AddProperties(debug::IntrospectionData&);
@@ -380,6 +385,8 @@ private:
bool is_desktop_active_;
+ grabber::GnomeKeyGrabber grabber_;
+
friend class UnityWindow;
};