summaryrefslogtreecommitdiff
diff options
authorWilliam Hua <william.hua@canonical.com>2014-04-18 01:08:05 +1200
committerWilliam Hua <william.hua@canonical.com>2014-04-18 01:08:05 +1200
commit37fc8ba650ee6f212f037acb7795868772b5ce84 (patch)
tree6d17849184af3152e86d0eee16f386bd2414dc1b
parentf7e3e1d0ad86546879981ebeeceb18902fe1bb55 (diff)
Rip everything out and start anew.
(bzr r3781.3.2)
-rw-r--r--lockscreen/CMakeLists.txt1
-rw-r--r--lockscreen/LockScreenAbstractShield.h6
-rw-r--r--lockscreen/LockScreenAccelerators.cpp468
-rw-r--r--lockscreen/LockScreenAccelerators.h94
-rw-r--r--lockscreen/LockScreenController.cpp133
-rw-r--r--lockscreen/LockScreenController.h5
-rw-r--r--lockscreen/LockScreenPanel.cpp581
-rw-r--r--lockscreen/LockScreenPanel.h73
-rw-r--r--lockscreen/LockScreenShield.cpp29
-rw-r--r--lockscreen/LockScreenShield.h3
-rw-r--r--lockscreen/LockScreenShieldFactory.cpp4
-rw-r--r--lockscreen/LockScreenShieldFactory.h4
-rw-r--r--tests/test_lockscreen_controller.cpp5
13 files changed, 745 insertions, 661 deletions
diff --git a/lockscreen/CMakeLists.txt b/lockscreen/CMakeLists.txt
index b32421f8f..0b2bbcd7f 100644
--- a/lockscreen/CMakeLists.txt
+++ b/lockscreen/CMakeLists.txt
@@ -23,6 +23,7 @@ set (LOCKSCREEN_SOURCES
LockScreenSettings.cpp
LockScreenShield.cpp
LockScreenShieldFactory.cpp
+ LockScreenAccelerators.cpp
LockScreenPanel.cpp
ScreenSaverDBusManager.cpp
UserAuthenticatorPam.cpp
diff --git a/lockscreen/LockScreenAbstractShield.h b/lockscreen/LockScreenAbstractShield.h
index 52f063e84..b6ced4261 100644
--- a/lockscreen/LockScreenAbstractShield.h
+++ b/lockscreen/LockScreenAbstractShield.h
@@ -25,6 +25,7 @@
#include <UnityCore/Indicators.h>
#include "unity-shared/MockableBaseWindow.h"
+#include "LockScreenAccelerators.h"
namespace unity
{
@@ -34,12 +35,13 @@ namespace lockscreen
class AbstractShield : public MockableBaseWindow
{
public:
- AbstractShield(session::Manager::Ptr const& session, indicator::Indicators::Ptr const& indicators, int monitor_num, bool is_primary)
+ AbstractShield(session::Manager::Ptr const& session, indicator::Indicators::Ptr const& indicators, Accelerators::Ptr const& accelerators, int monitor_num, bool is_primary)
: MockableBaseWindow("Unity Lockscreen")
, primary(is_primary)
, monitor(monitor_num)
, session_manager_(session)
, indicators_(indicators)
+ , accelerators_(accelerators)
{}
nux::Property<bool> primary;
@@ -48,6 +50,7 @@ public:
using MockableBaseWindow::RemoveLayout;
virtual bool IsIndicatorOpen() const = 0;
virtual void CheckCapsLockPrompt() = 0;
+ virtual void ActivatePanel() = 0;
sigc::signal<void, int, int> grab_motion;
sigc::signal<void, unsigned long, unsigned long> grab_key;
@@ -55,6 +58,7 @@ public:
protected:
session::Manager::Ptr session_manager_;
indicator::Indicators::Ptr indicators_;
+ Accelerators::Ptr accelerators_;
};
} // lockscreen
diff --git a/lockscreen/LockScreenAccelerators.cpp b/lockscreen/LockScreenAccelerators.cpp
new file mode 100644
index 000000000..7ee33e139
--- /dev/null
+++ b/lockscreen/LockScreenAccelerators.cpp
@@ -0,0 +1,468 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/*
+ * Copyright (C) 2014 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 "LockScreenAccelerators.h"
+
+#include <gtk/gtk.h>
+
+namespace unity
+{
+namespace lockscreen
+{
+
+static unsigned int KeysymToModifier(unsigned int keysym)
+{
+ switch (keysym)
+ {
+ case GDK_KEY_Shift_L:
+ case GDK_KEY_Shift_R:
+ return nux::KEY_MODIFIER_SHIFT;
+ case GDK_KEY_Control_L:
+ case GDK_KEY_Control_R:
+ return nux::KEY_MODIFIER_CTRL;
+ case GDK_KEY_Alt_L:
+ case GDK_KEY_Alt_R:
+ return nux::KEY_MODIFIER_ALT;
+ case GDK_KEY_Super_L:
+ case GDK_KEY_Super_R:
+ return nux::KEY_MODIFIER_SUPER;
+ }
+
+ return 0;
+}
+
+static unsigned int KeysymToPressedMask(unsigned int keysym)
+{
+ switch (keysym)
+ {
+ case GDK_KEY_Shift_L:
+ return LeftShiftPressed;
+ case GDK_KEY_Shift_R:
+ return RightShiftPressed;
+ case GDK_KEY_Control_L:
+ return LeftControlPressed;
+ case GDK_KEY_Control_R:
+ return RightControlPressed;
+ case GDK_KEY_Alt_L:
+ return LeftAltPressed;
+ case GDK_KEY_Alt_R:
+ return RightAltPressed;
+ case GDK_KEY_Super_L:
+ return LeftSuperPressed;
+ case GDK_KEY_Super_R:
+ return RightSuperPressed;
+ }
+
+ return 0;
+}
+
+static unsigned int KeysymToMirrorKeysym(unsigned int keysym)
+{
+ switch (keysym)
+ {
+ case GDK_KEY_Shift_L:
+ return GDK_KEY_Shift_R;
+ case GDK_KEY_Shift_R:
+ return GDK_KEY_Shift_L;
+ case GDK_KEY_Control_L:
+ return GDK_KEY_Control_R;
+ case GDK_KEY_Control_R:
+ return GDK_KEY_Control_L;
+ case GDK_KEY_Alt_L:
+ return GDK_KEY_Alt_R;
+ case GDK_KEY_Alt_R:
+ return GDK_KEY_Alt_L;
+ case GDK_KEY_Super_L:
+ return GDK_KEY_Super_R;
+ case GDK_KEY_Super_R:
+ return GDK_KEY_Super_L;
+ }
+
+ return 0;
+}
+
+Accelerator::Accelerator(unsigned int keysym,
+ unsigned int keycode,
+ unsigned int modifiers)
+ : keysym_(keysym)
+ , keycode_(keycode)
+ , modifiers_(modifiers)
+ , active_(true)
+ , activated_(false)
+{
+}
+
+Accelerator::Accelerator(std::string const& string)
+ : keysym_(0)
+ , keycode_(0)
+ , modifiers_(0)
+ , active_(true)
+ , activated_(false)
+{
+ guint keysym;
+ guint* keycodes;
+ GdkModifierType modifiers;
+
+ gtk_accelerator_parse_with_keycode(string.c_str(), &keysym, &keycodes, &modifiers);
+
+ /* gtk_accelerator_parse_with_keycode() might fail if the key is not in the
+ * default key map. gtk_accelerator_parse() might succeed in this case. */
+ if (keysym == 0 && keycodes == NULL && modifiers == 0)
+ gtk_accelerator_parse(string.c_str(), &keysym, &modifiers);
+
+ keysym_ = keysym;
+
+ if (keycodes != NULL)
+ {
+ keycode_ = keycodes[0];
+ g_free(keycodes);
+ }
+
+ if (modifiers & GDK_SHIFT_MASK)
+ modifiers_ |= nux::KEY_MODIFIER_SHIFT;
+ if (modifiers & GDK_CONTROL_MASK)
+ modifiers_ |= nux::KEY_MODIFIER_CTRL;
+ if (modifiers & GDK_MOD1_MASK)
+ modifiers_ |= nux::KEY_MODIFIER_ALT;
+ if (modifiers & GDK_SUPER_MASK)
+ modifiers_ |= nux::KEY_MODIFIER_SUPER;
+}
+
+bool Accelerator::operator==(Accelerator const& accelerator) const
+{
+ return keysym_ == accelerator.keysym_
+ && keycode_ == accelerator.keycode_
+ && modifiers_ == accelerator.modifiers_;
+}
+
+bool Accelerator::HandleKeyPress(unsigned int keysym,
+ unsigned int modifiers,
+ unsigned int press_state)
+{
+ auto is_modifier_only = keysym_ == 0 && keycode_ == 0 && modifiers_ != 0;
+ auto is_modifier_keysym = KeysymToModifier(keysym_);
+ auto modifier = KeysymToModifier(keysym);
+
+ if (modifiers == 0)
+ {
+ /* We're pressing a key when no other key is pressed. We can reset this
+ * accelerator back to its original enabled state. */
+ active_ = true;
+ activated_ = false;
+ }
+
+ if (!active_)
+ return false;
+
+ /* We need to cancel modifier-only accelerators in some cases. For example,
+ * we should cancel a Ctrl+Alt accelerator if Ctrl+Alt+T is pressed. */
+ if (is_modifier_only || is_modifier_keysym)
+ {
+ if (!modifier)
+ {
+ /* We pressed a non-modifier key for a modifier-only accelerator. */
+ active_ = false;
+ return false;
+ }
+ else if (keysym != keysym_ && (modifiers_ & modifier) == 0)
+ {
+ /* We pressed a modifier key that isn't the keysym and isn't one of the
+ * modifiers. */
+ active_ = false;
+ return false;
+ }
+ }
+ else if (!modifier)
+ {
+ /* We expect a non-modifier key to activate and one was pressed. */
+ if (modifiers == modifiers_)
+ {
+ /* The modifiers match. Check if the keysyms match. */
+ if (keysym == keysym_)
+ goto activate;
+ else
+ {
+ /* Otherwise, check if the keycodes match. Maybe the accelerator
+ * specifies a particular key code, or the keyboard layout changed. For
+ * example, if the accelerator is Ctrl+A and the user switches from a
+ * QWERTY to an AZERTY layout, we should accept Ctrl+Q so the user can
+ * cycle through the entire list of keyboard layouts. */
+
+ GdkKeymapKey* key;
+ gint keys;
+
+ if (gdk_keymap_get_entries_for_keyval(gdk_keymap_get_default(), keysym, &key, &keys))
+ {
+ for (auto i = 0; i < keys; i++)
+ {
+ if (key[i].keycode == keycode_)
+ {
+ g_free(key);
+ goto activate;
+ }
+ }
+
+ g_free(key);
+ }
+ }
+ }
+ }
+
+ return false;
+
+activate:
+ Activate.emit();
+ activated_ = true;
+
+ return true;
+}
+
+bool Accelerator::HandleKeyRelease(unsigned int keysym,
+ unsigned int modifiers,
+ unsigned int press_state)
+{
+ auto is_modifier_only = keysym_ == 0 && keycode_ == 0 && modifiers_ != 0;
+ auto is_modifier_keysym = KeysymToModifier(keysym_);
+ auto modifier = KeysymToModifier(keysym);
+
+ /* Don't activate on key release if we were activated on a key press. */
+ if (!active_ || activated_)
+ return false;
+
+ /* Check if the keysyms match. */
+ if (keysym == keysym_)
+ {
+ if (KeysymToModifier(keysym) == 0)
+ {
+ /* We released a non-modifier key. */
+ if (modifiers == modifiers_)
+ goto activate;
+ }
+ else
+ {
+ /* We released a modifier key. */
+ auto mirror_keysym = KeysymToMirrorKeysym(keysym);
+ auto is_mirror_pressed = press_state & KeysymToPressedMask(mirror_keysym);
+
+ /* Ctrl+Shift_R is different from Ctrl+Shift+Shift_R, so we must detect
+ * if the mirror key was pressed or not. */
+ if (is_mirror_pressed)
+ {
+ /* The mirrored modifier is pressed. */
+ if (modifiers == modifiers_)
+ goto activate;
+ }
+ else
+ {
+ /* The mirrored modifier wasn't pressed. Compare modifiers without it. */
+ if ((modifiers & ~KeysymToModifier(mirror_keysym)) == modifiers_)
+ goto activate;
+ }
+ }
+ }
+
+ if (is_modifier_only || is_modifier_keysym)
+ {
+ if (modifier)
+ {
+ /* We released a modifier key for a modifier-only accelerator. */
+
+ if (is_modifier_only)
+ {
+ /* The accelerator has no keysym or keycode. */
+
+ /* TODO: Normally we would goto activate here, but compiz is
+ * intercepting this case and handling it. This is bad because now we
+ * can't do anything here. Otherwise we'll do the same action twice. */
+ if (modifiers == modifiers_)
+ return false;
+ }
+ else
+ {
+ /* The accelerator has a modifier keysym. */
+ auto is_keysym_pressed = press_state & KeysymToPressedMask(keysym_);
+
+ if (is_keysym_pressed)
+ {
+ auto mirror_keysym = KeysymToMirrorKeysym(keysym_);
+ auto is_mirror_pressed = press_state & KeysymToPressedMask(mirror_keysym);
+
+ /* Ctrl+Shift_R is different from Ctrl+Shift+Shift_R, so we must detect
+ * if the mirror key was pressed or not. */
+ if (is_mirror_pressed)
+ {
+ /* The mirrored modifier is pressed. */
+ if (modifiers == modifiers_)
+ goto activate;
+ }
+ else
+ {
+ /* The mirrored modifier wasn't pressed. Compare modifiers without it. */
+ if ((modifiers & ~KeysymToModifier(mirror_keysym)) == modifiers_)
+ goto activate;
+ }
+ }
+ }
+ }
+ }
+ else if (keycode_ != 0 && modifiers == modifiers_)
+ {
+ /* Otherwise, check if the keycodes match. Maybe the accelerator
+ * specifies a particular key code, or the keyboard layout changed. For
+ * example, if the accelerator is Ctrl+A and the user switches from a
+ * QWERTY to an AZERTY layout, we should accept Ctrl+Q so the user can
+ * cycle through the entire list of keyboard layouts. */
+
+ GdkKeymapKey* key;
+ gint keys;
+
+ if (gdk_keymap_get_entries_for_keyval(gdk_keymap_get_default(), keysym, &key, &keys))
+ {
+ for (auto i = 0; i < keys; i++)
+ {
+ if (key[i].keycode == keycode_)
+ {
+ g_free(key);
+ goto activate;
+ }
+ }
+
+ g_free(key);
+ }
+ }
+
+ return false;
+
+activate:
+ Activate.emit();
+ activated_ = false;
+
+ return true;
+}
+
+Accelerators::Accelerators()
+ : press_state_(0)
+{
+}
+
+void Accelerators::Clear()
+{
+ accelerators_.clear();
+}
+
+void Accelerators::Add(Accelerator const& accelerator)
+{
+ accelerators_.push_back(accelerator);
+}
+
+void Accelerators::Remove(Accelerator const& accelerator)
+{
+ accelerators_.remove(accelerator);
+}
+
+bool Accelerators::HandleKeyPress(unsigned int keysym,
+ unsigned int modifiers)
+{
+ modifiers &= nux::KEY_MODIFIER_SHIFT
+ | nux::KEY_MODIFIER_CTRL
+ | nux::KEY_MODIFIER_ALT
+ | nux::KEY_MODIFIER_SUPER;
+
+ switch (keysym)
+ {
+ case GDK_KEY_Shift_L:
+ press_state_ |= LeftShiftPressed;
+ break;
+ case GDK_KEY_Shift_R:
+ press_state_ |= RightShiftPressed;
+ break;
+ case GDK_KEY_Control_L:
+ press_state_ |= LeftControlPressed;
+ break;
+ case GDK_KEY_Control_R:
+ press_state_ |= RightControlPressed;
+ break;
+ case GDK_KEY_Alt_L:
+ press_state_ |= LeftAltPressed;
+ break;
+ case GDK_KEY_Alt_R:
+ press_state_ |= RightAltPressed;
+ break;
+ case GDK_KEY_Super_L:
+ press_state_ |= LeftSuperPressed;
+ break;
+ case GDK_KEY_Super_R:
+ press_state_ |= RightSuperPressed;
+ break;
+ }
+
+ auto handled = false;
+
+ for (auto& accelerator : accelerators_)
+ handled = accelerator.HandleKeyPress(keysym, modifiers, press_state_) || handled;
+
+ return handled;
+}
+
+bool Accelerators::HandleKeyRelease(unsigned int keysym,
+ unsigned int modifiers)
+{
+ modifiers &= nux::KEY_MODIFIER_SHIFT
+ | nux::KEY_MODIFIER_CTRL
+ | nux::KEY_MODIFIER_ALT
+ | nux::KEY_MODIFIER_SUPER;
+
+ auto handled = false;
+
+ for (auto& accelerator : accelerators_)
+ handled = accelerator.HandleKeyRelease(keysym, modifiers, press_state_) || handled;
+
+ switch (keysym)
+ {
+ case GDK_KEY_Shift_L:
+ press_state_ &= ~LeftShiftPressed;
+ break;
+ case GDK_KEY_Shift_R:
+ press_state_ &= ~RightShiftPressed;
+ break;
+ case GDK_KEY_Control_L:
+ press_state_ &= ~LeftControlPressed;
+ break;
+ case GDK_KEY_Control_R:
+ press_state_ &= ~RightControlPressed;
+ break;
+ case GDK_KEY_Alt_L:
+ press_state_ &= ~LeftAltPressed;
+ break;
+ case GDK_KEY_Alt_R:
+ press_state_ &= ~RightAltPressed;
+ break;
+ case GDK_KEY_Super_L:
+ press_state_ &= ~LeftSuperPressed;
+ break;
+ case GDK_KEY_Super_R:
+ press_state_ &= ~RightSuperPressed;
+ break;
+ }
+
+ return handled;
+}
+
+} // lockscreen namespace
+} // unity namespace
diff --git a/lockscreen/LockScreenAccelerators.h b/lockscreen/LockScreenAccelerators.h
new file mode 100644
index 000000000..b0ad61e62
--- /dev/null
+++ b/lockscreen/LockScreenAccelerators.h
@@ -0,0 +1,94 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/*
+ * Copyright (C) 2014 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 UNITY_LOCKSCREEN_ACCELERATORS
+#define UNITY_LOCKSCREEN_ACCELERATORS
+
+namespace unity
+{
+namespace lockscreen
+{
+
+enum
+{
+ LeftShiftPressed = 0x01,
+ LeftControlPressed = 0x02,
+ LeftAltPressed = 0x04,
+ LeftSuperPressed = 0x08,
+ RightShiftPressed = 0x10,
+ RightControlPressed = 0x20,
+ RightAltPressed = 0x40,
+ RightSuperPressed = 0x80
+};
+
+class Accelerator
+{
+public:
+ Accelerator(unsigned int keysym, unsigned int keycode, unsigned int modifiers);
+ explicit Accelerator(std::string const& string);
+
+ bool operator==(Accelerator const& accelerator) const;
+
+ sigc::signal<void> Activate;
+
+private:
+ bool HandleKeyPress(unsigned int keysym,
+ unsigned int modifiers,
+ unsigned int press_state);
+ bool HandleKeyRelease(unsigned int keysym,
+ unsigned int modifiers,
+ unsigned int press_state);
+
+ unsigned int keysym_;
+ unsigned int keycode_;
+ unsigned int modifiers_;
+
+ bool active_;
+ bool activated_;
+
+ friend class Accelerators;
+};
+
+class Accelerators
+{
+public:
+ typedef std::shared_ptr<Accelerators> Ptr;
+
+ Accelerators();
+
+ void Clear();
+
+ void Add(Accelerator const& accelerator);
+ void Remove(Accelerator const& accelerator);
+
+ bool HandleKeyPress(unsigned int keysym,
+ unsigned int modifiers);
+ bool HandleKeyRelease(unsigned int keysym,
+ unsigned int modifiers);
+
+private:
+ std::list<Accelerator> accelerators_;
+
+ unsigned int press_state_;
+};
+
+} // lockscreen namespace
+} // unity namespace
+
+#endif // UNITY_LOCKSCREEN_ACCELERATORS
diff --git a/lockscreen/LockScreenController.cpp b/lockscreen/LockScreenController.cpp
index ef03be97f..b1b61a1a6 100644
--- a/lockscreen/LockScreenController.cpp
+++ b/lockscreen/LockScreenController.cpp
@@ -38,6 +38,24 @@ const unsigned int IDLE_FADE_DURATION = 10000;
const unsigned int LOCK_FADE_DURATION = 400;
const unsigned int POST_LOCK_SCREENSAVER_WAIT = 2;
+const char* MEDIA_KEYS_SCHEMA = "org.gnome.settings-daemon.plugins.media-keys";
+const char* MEDIA_KEYS_KEY_VOLUME_MUTE = "volume-mute";
+const char* MEDIA_KEYS_KEY_VOLUME_DOWN = "volume-down";
+const char* MEDIA_KEYS_KEY_VOLUME_UP = "volume-up";
+const char* INPUT_SWITCH_SCHEMA = "org.gnome.desktop.wm.keybindings";
+const char* INPUT_SWITCH_KEY_PREVIOUS_SOURCE = "switch-input-source-backward";
+const char* INPUT_SWITCH_KEY_NEXT_SOURCE = "switch-input-source";
+
+const char* INDICATOR_ACTION_INTERFACE = "org.gtk.Actions";
+const char* INDICATOR_METHOD_ACTIVATE = "Activate";
+const char* INDICATOR_SOUND_BUS_NAME = "com.canonical.indicator.sound";
+const char* INDICATOR_SOUND_OBJECT_PATH = "/com/canonical/indicator/sound";
+const char* INDICATOR_SOUND_ACTION_MUTE = "mute";
+const char* INDICATOR_SOUND_ACTION_SCROLL = "scroll";
+const char* INDICATOR_KEYBOARD_BUS_NAME = "com.canonical.indicator.keyboard";
+const char* INDICATOR_KEYBOARD_OBJECT_PATH = "/com/canonical/indicator/keyboard";
+const char* INDICATOR_KEYBOARD_ACTION_SCROLL = "locked_scroll";
+
class BlankWindow : public nux::BaseWindow
{
public:
@@ -57,6 +75,7 @@ Controller::Controller(DBusManager::Ptr const& dbus_manager,
: opacity([this] { return fade_animator_.GetCurrentValue(); })
, dbus_manager_(dbus_manager)
, session_manager_(session_manager)
+ , accelerators_(new Accelerators)
, upstart_wrapper_(upstart_wrapper)
, shield_factory_(shield_factory)
, fade_animator_(LOCK_FADE_DURATION)
@@ -141,6 +160,117 @@ Controller::Controller(DBusManager::Ptr const& dbus_manager,
});
}
+void Controller::ActivatePanel()
+{
+ if (primary_shield_.IsValid())
+ primary_shield_->ActivatePanel();
+}
+
+static void ActivateIndicator(std::string const& bus_name,
+ std::string const& object_path,
+ std::string const& action_name,
+ glib::Variant const& parameters)
+{
+ GVariantBuilder builder;
+
+ g_variant_builder_init(&builder, G_VARIANT_TYPE("(sava{sv})"));
+ g_variant_builder_add(&builder, "s", action_name.c_str());
+
+ if (parameters)
+ g_variant_builder_add_parsed(&builder, "[%v]", (GVariant*) parameters);
+ else
+ g_variant_builder_add_parsed(&builder, "@av []");
+
+ g_variant_builder_add_parsed(&builder, "@a{sv} []");
+
+ auto proxy = std::make_shared<glib::DBusProxy>(bus_name, object_path, INDICATOR_ACTION_INTERFACE, G_BUS_TYPE_SESSION);
+ proxy->CallBegin(INDICATOR_METHOD_ACTIVATE, g_variant_builder_end(&builder), [proxy] (GVariant*, glib::Error const&) {});
+}
+
+static void ActivateIndicatorSound(std::string const& action_name,
+ glib::Variant const& parameters)
+{
+ ActivateIndicator(INDICATOR_SOUND_BUS_NAME,
+ INDICATOR_SOUND_OBJECT_PATH,
+ action_name,
+ parameters);
+}
+
+static void MuteIndicatorSound()
+{
+ ActivateIndicatorSound(INDICATOR_SOUND_ACTION_MUTE, nullptr);
+}
+
+static void ScrollIndicatorSound(int offset)
+{
+ ActivateIndicatorSound(INDICATOR_SOUND_ACTION_SCROLL, g_variant_new_int32(offset));
+}
+
+static void ActivateIndicatorKeyboard(std::string const& action_name,
+ glib::Variant const& parameters)
+{
+ ActivateIndicator(INDICATOR_KEYBOARD_BUS_NAME,
+ INDICATOR_KEYBOARD_OBJECT_PATH,
+ action_name,
+ parameters);
+}
+
+static void ScrollIndicatorKeyboard(int offset)
+{
+ ActivateIndicatorKeyboard(INDICATOR_KEYBOARD_ACTION_SCROLL, g_variant_new_int32(-offset));
+}
+
+void Controller::ParseAccelerators()
+{
+ accelerators_->Clear();
+
+ auto media_keys_settings = glib::Object<GSettings>(g_settings_new(MEDIA_KEYS_SCHEMA));
+ auto input_switch_settings = glib::Object<GSettings>(g_settings_new(INPUT_SWITCH_SCHEMA));
+
+ auto activate_panel = WindowManager::Default().activate_indicators_key();
+ auto accelerator = Accelerator(activate_panel.second, 0, activate_panel.first);
+ accelerator.Activate.connect(std::bind(std::mem_fn(&Controller::ActivatePanel), this));
+ accelerators_->Add(accelerator);
+
+ accelerator = Accelerator(glib::String(g_settings_get_string(media_keys_settings, MEDIA_KEYS_KEY_VOLUME_MUTE)));
+ accelerator.Activate.connect(std::function<void ()>(MuteIndicatorSound));
+ accelerators_->Add(accelerator);
+
+ accelerator = Accelerator(glib::String(g_settings_get_string(media_keys_settings, MEDIA_KEYS_KEY_VOLUME_DOWN)));
+ accelerator.Activate.connect(std::bind(ScrollIndicatorSound, -1));
+ accelerators_->Add(accelerator);
+
+ accelerator = Accelerator(glib::String(g_settings_get_string(media_keys_settings, MEDIA_KEYS_KEY_VOLUME_UP)));
+ accelerator.Activate.connect(std::bind(ScrollIndicatorSound, +1));
+ accelerators_->Add(accelerator);
+
+ auto variant = glib::Variant(g_settings_get_value(input_switch_settings, INPUT_SWITCH_KEY_PREVIOUS_SOURCE), glib::StealRef());
+
+ if (g_variant_n_children(variant) > 0)
+ {
+ const gchar* string;
+
+ g_variant_get_child(variant, 0, "&s", &string);
+
+ accelerator = Accelerator(string);
+ accelerator.Activate.connect(std::bind(ScrollIndicatorKeyboard, -1));
+ accelerators_->Add(accelerator);
+ }
+
+ variant = glib::Variant(g_settings_get_value(input_switch_settings, INPUT_SWITCH_KEY_NEXT_SOURCE), glib::StealRef());
+
+ if (g_variant_n_children(variant) > 0)
+ {
+ const gchar* string;
+
+ g_variant_get_child(variant, 0, "&s", &string);
+
+ accelerator = Accelerator(string);
+ accelerator.Activate.connect(std::bind(ScrollIndicatorKeyboard, +1));
+ accelerators_->Add(accelerator);
+ }
+}
+
void Controller::ResetPostLockScreenSaver()
{
screensaver_post_lock_timeout_.reset();
@@ -186,7 +316,7 @@ void Controller::EnsureShields(std::vector<nux::Geometry> const& monitors)
if (i >= shields_size)
{
- shield = shield_factory_->CreateShield(session_manager_, indicators_, i, i == primary);
+ shield = shield_factory_->CreateShield(session_manager_, indicators_, accelerators_, i, i == primary);
is_new = true;
}
@@ -390,6 +520,7 @@ void Controller::LockScreen()
indicators_ = std::make_shared<indicator::LockScreenDBusIndicators>();
upstart_wrapper_->Emit("desktop-lock");
+ ParseAccelerators();
ShowShields();
}
diff --git a/lockscreen/LockScreenController.h b/lockscreen/LockScreenController.h
index 434b95c13..bf44a3193 100644
--- a/lockscreen/LockScreenController.h
+++ b/lockscreen/LockScreenController.h
@@ -60,6 +60,8 @@ private:
void BlankWindowGrabEnable(bool grab);
void SimulateActivity();
void ResetPostLockScreenSaver();
+ void ActivatePanel();
+ void ParseAccelerators();
void OnLockRequested(bool prompt);
void OnUnlockRequested();
@@ -74,6 +76,7 @@ private:
DBusManager::Ptr dbus_manager_;
session::Manager::Ptr session_manager_;
indicator::Indicators::Ptr indicators_;
+ Accelerators::Ptr accelerators_;
UpstartWrapper::Ptr upstart_wrapper_;
ShieldFactoryInterface::Ptr shield_factory_;
@@ -98,4 +101,4 @@ private:
}
}
-#endif \ No newline at end of file
+#endif
diff --git a/lockscreen/LockScreenPanel.cpp b/lockscreen/LockScreenPanel.cpp
index f77cae6d6..3fe2a0f7e 100644
--- a/lockscreen/LockScreenPanel.cpp
+++ b/lockscreen/LockScreenPanel.cpp
@@ -21,7 +21,6 @@
#include <boost/algorithm/string/trim.hpp>
#include <Nux/HLayout.h>
-#include <UnityCore/Variant.h>
#include "LockScreenSettings.h"
#include "panel/PanelIndicatorsView.h"
@@ -39,30 +38,6 @@ namespace lockscreen
namespace
{
const RawPixel PADDING = 5_em;
-
-const std::string MEDIA_KEYS_SCHEMA = "org.gnome.settings-daemon.plugins.media-keys";
-const std::string MEDIA_KEYS_VOLUME_MUTE = "volume-mute";
-const std::string MEDIA_KEYS_VOLUME_DOWN = "volume-down";
-const std::string MEDIA_KEYS_VOLUME_UP = "volume-up";
-const std::string INPUT_SWITCH_SCHEMA = "org.gnome.desktop.wm.keybindings";
-const std::string INPUT_SWITCH_PREVIOUS = "switch-input-source-backward";
-const std::string INPUT_SWITCH_NEXT = "switch-input-source";
-
-const std::string INDICATOR_KEYBOARD_BUS_NAME = "com.canonical.indicator.keyboard";
-const std::string INDICATOR_KEYBOARD_OBJECT_PATH = "/com/canonical/indicator/keyboard";
-const std::string INDICATOR_SOUND_BUS_NAME = "com.canonical.indicator.sound";
-const std::string INDICATOR_SOUND_OBJECT_PATH = "/com/canonical/indicator/sound";
-const std::string INDICATOR_ACTION_INTERFACE = "org.gtk.Actions";
-const std::string INDICATOR_METHOD_ACTIVATE = "Activate";
-
-const std::string INDICATOR_KEYBOARD_ACTION_SCROLL = "locked_scroll";
-const std::string INDICATOR_SOUND_ACTION_SCROLL = "scroll";
-const std::string INDICATOR_SOUND_ACTION_MUTE = "mute";
-
-const unsigned int MODIFIERS = nux::KEY_MODIFIER_SHIFT |
- nux::KEY_MODIFIER_CTRL |
- nux::KEY_MODIFIER_ALT |
- nux::KEY_MODIFIER_SUPER;
}
using namespace indicator;
@@ -74,6 +49,7 @@ Panel::Panel(int monitor_, Indicators::Ptr const& indicators, session::Manager::
, monitor(monitor_)
, indicators_(indicators)
, needs_geo_sync_(true)
+ , activate_panel_(false)
{
double scale = unity::Settings::Instance().em(monitor)->DPIScale();
auto* layout = new nux::HLayout();
@@ -112,11 +88,6 @@ Panel::Panel(int monitor_, Indicators::Ptr const& indicators, session::Manager::
BuildTexture();
QueueRelayout();
});
-
- ParseAccelerators();
-
- key_down.connect(sigc::mem_fun(this, &Panel::OnKeyDown));
- key_up.connect(sigc::mem_fun(this, &Panel::OnKeyUp));
}
void Panel::BuildTexture()
@@ -245,560 +216,20 @@ void Panel::Draw(nux::GraphicsEngine& graphics_engine, bool force_draw)
}
}
-Panel::Accelerator::Accelerator(unsigned int keysym, unsigned int keycode, unsigned int modifiers)
- : keysym_(keysym)
- , keycode_(keycode)
- , modifiers_(modifiers)
- , active_(true)
- , activated_(false)
- , match_(false)
-{
-}
-
-void Panel::Accelerator::Reset()
-{
- active_ = true;
- activated_ = false;
- match_ = false;
-}
-
-Panel::Accelerator Panel::ParseAcceleratorString(std::string const& string) const
-{
- Accelerator accelerator;
-
- guint gtk_keysym;
- guint* gtk_keycodes;
- GdkModifierType gtk_modifiers;
- gtk_accelerator_parse_with_keycode(string.c_str(), &gtk_keysym, &gtk_keycodes, &gtk_modifiers);
-
- /* gtk_accelerator_parse_with_keycode() might fail if the key isn't in the default key map.
- * In that case, try it again without looking for keycodes. */
- if (gtk_keysym == 0 && gtk_modifiers == 0)
- {
- g_free(gtk_keycodes);
- gtk_keycodes = NULL;
- gtk_accelerator_parse(string.c_str(), &gtk_keysym, &gtk_modifiers);
- }
-
- accelerator.keysym_ = gtk_keysym;
-
- if (gtk_keycodes != NULL)
- accelerator.keycode_ = gtk_keycodes[0];
-
- g_free(gtk_keycodes);
-
- if (gtk_modifiers & GDK_SHIFT_MASK)
- accelerator.modifiers_ |= nux::KEY_MODIFIER_SHIFT;
- if (gtk_modifiers & GDK_CONTROL_MASK)
- accelerator.modifiers_ |= nux::KEY_MODIFIER_CTRL;
- if (gtk_modifiers & GDK_MOD1_MASK)
- accelerator.modifiers_ |= nux::KEY_MODIFIER_ALT;
- if (gtk_modifiers & GDK_SUPER_MASK)
- accelerator.modifiers_ |= nux::KEY_MODIFIER_SUPER;
-
- return accelerator;
-}
-
-void Panel::ParseAccelerators()
-{
- auto media_key_settings = glib::Object<GSettings>(g_settings_new(MEDIA_KEYS_SCHEMA.c_str()));
- auto input_switch_settings = glib::Object<GSettings>(g_settings_new(INPUT_SWITCH_SCHEMA.c_str()));
- auto activate_indicators_key = WindowManager::Default().activate_indicators_key();
-
- activate_indicator_ = Accelerator(activate_indicators_key.second, 0, activate_indicators_key.first);
- volume_mute_ = ParseAcceleratorString(glib::String(g_settings_get_string(media_key_settings, MEDIA_KEYS_VOLUME_MUTE.c_str())));
- volume_down_ = ParseAcceleratorString(glib::String(g_settings_get_string(media_key_settings, MEDIA_KEYS_VOLUME_DOWN.c_str())));
- volume_up_ = ParseAcceleratorString(glib::String(g_settings_get_string(media_key_settings, MEDIA_KEYS_VOLUME_UP.c_str())));
-
- auto variant = glib::Variant(g_settings_get_value(input_switch_settings, INPUT_SWITCH_PREVIOUS.c_str()), glib::StealRef());
-
- if (g_variant_n_children(variant) > 0)
- {
- const gchar *accelerator;
- g_variant_get_child(variant, 0, "&s", &accelerator);
- previous_source_ = ParseAcceleratorString(accelerator);
- }
- else
- previous_source_ = Accelerator();
-
- variant = glib::Variant(g_settings_get_value(input_switch_settings, INPUT_SWITCH_NEXT.c_str()), glib::StealRef());
-
- if (g_variant_n_children(variant) > 0)
- {
- const gchar *accelerator;
- g_variant_get_child(variant, 0, "&s", &accelerator);
- next_source_ = ParseAcceleratorString(accelerator);
- }
- else
- next_source_ = Accelerator();
-}
-
-bool Panel::WillHandleKeyEvent(unsigned int event_type, unsigned long keysym, unsigned long modifiers)
-{
- auto is_press = event_type == nux::EVENT_KEY_DOWN;
-
- /* Update modifier states on key press. */
- if (is_press)
- {
- switch (keysym)
- {
- case GDK_KEY_Shift_L:
- left_shift = is_press;
- break;
- case GDK_KEY_Shift_R:
- right_shift = is_press;
- break;
- case GDK_KEY_Control_L:
- left_control = is_press;
- break;
- case GDK_KEY_Control_R:
- right_control = is_press;
- break;
- case GDK_KEY_Alt_L:
- left_alt = is_press;
- break;
- case GDK_KEY_Alt_R:
- right_alt = is_press;
- break;
- case GDK_KEY_Super_L:
- left_super = is_press;
- break;
- case GDK_KEY_Super_R:
- right_super = is_press;
- break;
- }
- }
-
- /* If we're just pressing a key and no modifiers are pressed,
- * then we can start accepting new actions again. */
- if (is_press && (modifiers & MODIFIERS) == 0)
- {
- activate_indicator_.Reset();
- volume_mute_.Reset();
- volume_down_.Reset();
- volume_up_.Reset();
- previous_source_.Reset();
- next_source_.Reset();
- }
-
- /* We may have to disable the accelerator if this press invalidates it.
- * An example is pressing Ctrl+Alt+T which should cancel a Ctrl+Alt
- * accelerator. */
- MaybeDisableAccelerator(is_press, keysym, modifiers, activate_indicator_);
- MaybeDisableAccelerator(is_press, keysym, modifiers, volume_mute_);
- MaybeDisableAccelerator(is_press, keysym, modifiers, volume_down_);
- MaybeDisableAccelerator(is_press, keysym, modifiers, volume_up_);
- MaybeDisableAccelerator(is_press, keysym, modifiers, previous_source_);
- MaybeDisableAccelerator(is_press, keysym, modifiers, next_source_);
-
- /* We store the match here because IsMatch() is only valid here,
- * and not in the OnKeyDown()/OnKeyUp() functions. */
- activate_indicator_.match_ = IsMatch(is_press, keysym, modifiers, activate_indicator_);
- volume_mute_.match_ = IsMatch(is_press, keysym, modifiers, volume_mute_);
- volume_down_.match_ = IsMatch(is_press, keysym, modifiers, volume_down_);
- volume_up_.match_ = IsMatch(is_press, keysym, modifiers, volume_up_);
- previous_source_.match_ = IsMatch(is_press, keysym, modifiers, previous_source_);
- next_source_.match_ = IsMatch(is_press, keysym, modifiers, next_source_);
-
- /* Update modifier states on key release. */
- if (!is_press)
- {
- switch (keysym)
- {
- case GDK_KEY_Shift_L:
- left_shift = is_press;
- break;
- case GDK_KEY_Shift_R:
- right_shift = is_press;
- break;
- case GDK_KEY_Control_L:
- left_control = is_press;
- break;
- case GDK_KEY_Control_R:
- right_control = is_press;
- break;
- case GDK_KEY_Alt_L:
- left_alt = is_press;
- break;
- case GDK_KEY_Alt_R:
- right_alt = is_press;
- break;
- case GDK_KEY_Super_L:
- left_super = is_press;
- break;
- case GDK_KEY_Super_R:
- right_super = is_press;
- break;
- }
- }
-
- return activate_indicator_.match_ ||
- volume_mute_.match_ ||
- volume_down_.match_ ||
- volume_up_.match_ ||
- previous_source_.match_ ||
- next_source_.match_;
-}
-
bool Panel::InspectKeyEvent(unsigned int event_type, unsigned int keysym, const char*)
{
- return true;
-}
-
-bool Panel::IsModifier(unsigned int keysym) const
-{
- return ToModifier(keysym);
-}
-
-unsigned int Panel::ToModifier(unsigned int keysym) const
-{
- switch (keysym)
- {
- case GDK_KEY_Shift_L:
- case GDK_KEY_Shift_R:
- return nux::KEY_MODIFIER_SHIFT;
- case GDK_KEY_Control_L:
- case GDK_KEY_Control_R:
- return nux::KEY_MODIFIER_CTRL;
- case GDK_KEY_Alt_L:
- case GDK_KEY_Alt_R:
- return nux::KEY_MODIFIER_ALT;
- case GDK_KEY_Super_L:
- case GDK_KEY_Super_R:
- return nux::KEY_MODIFIER_SUPER;
- default:
- return 0;
- }
-}
-
-void Panel::MaybeDisableAccelerator(bool is_press,
- unsigned int keysym,
- unsigned int state,
- Accelerator& accelerator) const
-{
- auto is_modifier_only = accelerator.keysym_ == 0 && accelerator.keycode_ == 0 && accelerator.modifiers_ != 0;
- auto keysym_modifier = ToModifier(accelerator.keysym_);
-
- if (is_modifier_only || keysym_modifier)
- {
- if (is_press)
- {
- /* We may have to disable the accelerator if this press invalidates it.
- * An example is pressing Ctrl+Alt+T for a Ctrl+Alt accelerator. */
-
- if (!IsModifier(keysym))
- {
- /* We pressed a non-modifier key: disable the accelerator. */
- accelerator.active_ = false;
- }
- else if (keysym != accelerator.keysym_ && (ToModifier(keysym) & accelerator.modifiers_) == 0)
- {
- /* We pressed a modifier key that isn't the keysym or one of the modifiers: disable the accelerator. */
- accelerator.active_ = false;
- }
- }
- }
-}
-
-/* This function is only valid in WillHandleKeyEvent because
- * that's the only place the modifier key state is valid. */
-
-bool Panel::IsMatch(bool is_press,
- unsigned int keysym,
- unsigned int state,
- Accelerator const& accelerator) const
-{
- state &= MODIFIERS;
-
- /* Inactive accelerators never match. */
- if (!accelerator.active_)
- return false;
-
- /* Do the easiest check and compare keysyms.
- * But we must be careful with modifier-only accelerators. */
- if (keysym == accelerator.keysym_)
- {
- if (!IsModifier(keysym))
- {
- /* A non-modifier key was pressed/released, so just compare modifiers. */
- if (state == accelerator.modifiers_)
- return true;
- }
- else if (!is_press)
- {
- /* A modifier key was released, so compare modifiers ignoring that key. */
-
- auto is_mirror_pressed = false;
-
- switch (keysym)
- {
- case GDK_KEY_Shift_L:
- is_mirror_pressed = right_shift;
- break;
- case GDK_KEY_Shift_R:
- is_mirror_pressed = left_shift;
- break;
- case GDK_KEY_Control_L:
- is_mirror_pressed = right_control;
- break;
- case GDK_KEY_Control_R:
- is_mirror_pressed = left_control;
- break;
- case GDK_KEY_Alt_L:
- is_mirror_pressed = right_alt;
- break;
- case GDK_KEY_Alt_R:
- is_mirror_pressed = left_alt;
- break;
- case GDK_KEY_Super_L:
- is_mirror_pressed = right_super;
- break;
- case GDK_KEY_Super_R:
- is_mirror_pressed = left_super;
- break;
- }
-
- if (is_mirror_pressed)
- {
- /* We can just compare the state directly. */
- if (state == accelerator.modifiers_)
- return true;
- }
- else
- {
- /* We must pretend the state doesn't include keysym's modifier. */
- if ((state & ~ToModifier(keysym)) == accelerator.modifiers_)
- return true;
- }
- }
- }
-
- auto is_modifier_only = accelerator.keysym_ == 0 && accelerator.keycode_ == 0 && accelerator.modifiers_ != 0;
- auto keysym_modifier = ToModifier(accelerator.keysym_);
-
- if (is_modifier_only || keysym_modifier)
- {
- /* The accelerator consists of only modifier keys. */
-
- if (!is_press && IsModifier(keysym))
- {
- /* We're releasing a modifier key. */
-
- if (is_modifier_only)
- {
- /* Just ensure the states match in this case. */
- if (state == accelerator.modifiers_)
- {
- /* TODO: We would normally return true here, but for some reason
- * compiz handles it. This is bad because it means we have to do
- * nothing in this case where we would normally handle it.... */
- return false;
- }
- }
- else if (keysym_modifier)
- {
- auto is_keysym_pressed = false;
- auto is_mirror_pressed = false;
-
- /* Check that accelerator.keysym_ is pressed. */
- switch (accelerator.keysym_)
- {
- case GDK_KEY_Shift_L:
- is_keysym_pressed = left_shift;
- is_mirror_pressed = right_shift;
- break;
- case GDK_KEY_Shift_R:
- is_keysym_pressed = right_shift;
- is_mirror_pressed = left_shift;
- break;
- case GDK_KEY_Control_L:
- is_keysym_pressed = left_control;
- is_mirror_pressed = right_control;
- break;
- case GDK_KEY_Control_R:
- is_keysym_pressed = right_control;
- is_mirror_pressed = left_control;
- break;
- case GDK_KEY_Alt_L:
- is_keysym_pressed = left_alt;
- is_mirror_pressed = right_alt;
- break;
- case GDK_KEY_Alt_R:
- is_keysym_pressed = right_alt;
- is_mirror_pressed = left_alt;
- break;
- case GDK_KEY_Super_L:
- is_keysym_pressed = left_super;
- is_mirror_pressed = right_super;
- break;
- case GDK_KEY_Super_R:
- is_keysym_pressed = right_super;
- is_mirror_pressed = left_super;
- break;
- }
-
- if (is_keysym_pressed)
- {
- /* If the mirror key is not pressed, clear it from the state. */
- if (!is_mirror_pressed)
- state &= ~ToModifier(accelerator.keysym_);
-
- /* Check that the states are matching. */
- if (state == accelerator.modifiers_)
- return true;
- }
- }
- }
- }
- else if (accelerator.keycode_ != 0 && state == accelerator.modifiers_)
- {
- /* The keysyms might be different, but the keycodes might be the same.
- * For example, if the switching shortcut is Ctrl+A, we want Ctrl+Q to
- * match on an AZERTY layout. Otherwise, you can't cycle through a full
- * list of keyboard layouts with one accelerator. Or the accelerator may
- * not even have a keysym at all. Either way, check for both these cases.
- * Note that we don't want to check this for the modifier-only case, as
- * it's already handled specially above. */
-
- gint n_keys;
- GdkKeymapKey *keys;
-
- if (gdk_keymap_get_entries_for_keyval(gdk_keymap_get_default(), keysym, &keys, &n_keys))
- {
- auto is_match = false;
-
- for (auto i = 0; i < n_keys && !is_match; i++)
- is_match = keys[i].keycode == accelerator.keycode_;
-
- g_free(keys);
-
- if (is_match)
- return true;
- }
- }
-
- return false;
-}
-
-void Panel::OnKeyDown(unsigned long event,
- unsigned long keysym,
- unsigned long state,
- const char* text,
- unsigned short repeat)
-{
- if (activate_indicator_.match_)
+ if (activate_panel_)
{
ActivateFirst();
- activate_indicator_.activated_ = true;
- }
- else if (volume_mute_.match_)
- {
- ActivateSoundAction(INDICATOR_SOUND_ACTION_MUTE);
- volume_mute_.activated_ = true;
- }
- else if (volume_down_.match_)
- {
- ActivateSoundAction(INDICATOR_SOUND_ACTION_SCROLL, g_variant_new_int32(-1));
- volume_down_.activated_ = true;
- }
- else if (volume_up_.match_)
- {
- ActivateSoundAction(INDICATOR_SOUND_ACTION_SCROLL, g_variant_new_int32(+1));
- volume_up_.activated_ = true;
+ activate_panel_ = false;
}
- else if (previous_source_.match_)
- {
- ActivateKeyboardAction(INDICATOR_KEYBOARD_ACTION_SCROLL, g_variant_new_int32(+1));
- previous_source_.activated_ = true;
- }
- else if (next_source_.match_)
- {
- ActivateKeyboardAction(INDICATOR_KEYBOARD_ACTION_SCROLL, g_variant_new_int32(-1));
- next_source_.activated_ = true;
- }
-}
-
-void Panel::OnKeyUp(unsigned int keysym,
- unsigned long keycode,
- unsigned long state)
-{
- /* We only want to act if we didn't activate the action on key
- * down. Once we see the key up, we can start accepting actions
- * again. */
-
- if (activate_indicator_.match_)
- {
- if (!activate_indicator_.activated_)
- ActivateFirst();
-
- activate_indicator_.Reset();
- }
- else if (volume_mute_.match_)
- {
- if (!volume_mute_.activated_)
- ActivateSoundAction(INDICATOR_SOUND_ACTION_MUTE);
-
- volume_mute_.Reset();
- }
- else if (volume_down_.match_)
- {
- if (!volume_down_.activated_)
- ActivateSoundAction(INDICATOR_SOUND_ACTION_SCROLL, g_variant_new_int32(-1));
-
- volume_down_.Reset();
- }
- else if (volume_up_.match_)
- {
- if (!volume_up_.activated_)
- ActivateSoundAction(INDICATOR_SOUND_ACTION_SCROLL, g_variant_new_int32(+1));
- volume_up_.Reset();
- }
- else if (previous_source_.match_)
- {
- if (!previous_source_.activated_)
- ActivateKeyboardAction(INDICATOR_KEYBOARD_ACTION_SCROLL, g_variant_new_int32(+1));
-
- previous_source_.Reset();
- }
- else if (next_source_.match_)
- {
- if (!next_source_.activated_)
- ActivateKeyboardAction(INDICATOR_KEYBOARD_ACTION_SCROLL, g_variant_new_int32(-1));
-
- next_source_.Reset();
- }
-}
-
-void Panel::ActivateIndicatorAction(std::string const& bus_name,
- std::string const& object_path,
- std::string const& action,
- glib::Variant const& parameter) const
-{
- GVariantBuilder builder;
-
- g_variant_builder_init(&builder, G_VARIANT_TYPE("(sava{sv})"));
- g_variant_builder_add(&builder, "s", action.c_str());
-
- if (parameter)
- g_variant_builder_add_parsed(&builder, "[%v]", (GVariant*) parameter);
- else
- g_variant_builder_add_parsed(&builder, "@av []");
-
- g_variant_builder_add_parsed(&builder, "@a{sv} []");
-
- auto proxy = std::make_shared<glib::DBusProxy>(bus_name, object_path, INDICATOR_ACTION_INTERFACE, G_BUS_TYPE_SESSION);
- proxy->CallBegin(INDICATOR_METHOD_ACTIVATE, g_variant_builder_end(&builder), [proxy] (GVariant*, glib::Error const&) {});
-}
-
-void Panel::ActivateKeyboardAction(std::string const& action, glib::Variant const& parameter) const
-{
- ActivateIndicatorAction(INDICATOR_KEYBOARD_BUS_NAME, INDICATOR_KEYBOARD_OBJECT_PATH, action, parameter);
+ return true;
}
-void Panel::ActivateSoundAction(std::string const& action, glib::Variant const& parameter) const
+void Panel::ActivatePanel()
{
- ActivateIndicatorAction(INDICATOR_SOUND_BUS_NAME, INDICATOR_SOUND_OBJECT_PATH, action, parameter);
+ activate_panel_ = true;
}
}
diff --git a/lockscreen/LockScreenPanel.h b/lockscreen/LockScreenPanel.h
index be4c5098c..aaafbfeb2 100644
--- a/lockscreen/LockScreenPanel.h
+++ b/lockscreen/LockScreenPanel.h
@@ -22,10 +22,8 @@
#include <Nux/Nux.h>
#include <Nux/View.h>
-#include <UnityCore/GLibDBusProxy.h>
-#include <UnityCore/GLibSource.h>
-#include <UnityCore/GLibWrapper.h>
#include <UnityCore/Indicators.h>
+#include <UnityCore/GLibSource.h>
#include <UnityCore/SessionManager.h>
namespace unity
@@ -46,7 +44,7 @@ public:
nux::Property<bool> active;
nux::Property<int> monitor;
- bool WillHandleKeyEvent(unsigned int event_type, unsigned long keysym, unsigned long modifiers);
+ void ActivatePanel();
protected:
void Draw(nux::GraphicsEngine& GfxContext, bool force_draw) override;
@@ -72,72 +70,7 @@ private:
nux::Point tracked_pointer_pos_;
glib::Source::UniquePtr track_menu_pointer_timeout_;
- unsigned int left_shift : 1;
- unsigned int right_shift : 1;
- unsigned int left_control : 1;
- unsigned int right_control : 1;
- unsigned int left_alt : 1;
- unsigned int right_alt : 1;
- unsigned int left_super : 1;
- unsigned int right_super : 1;
-
- class Accelerator
- {
- public:
- unsigned int keysym_;
- unsigned int keycode_;
- unsigned int modifiers_;
- bool active_;
- bool activated_;
- bool match_;
-
- explicit Accelerator(unsigned int keysym = 0, unsigned int keycode = 0, unsigned int modifiers = 0);
-
- void Reset();
- };
-
- Accelerator ParseAcceleratorString(std::string const& string) const;
-
- void ParseAccelerators();
-
- Accelerator activate_indicator_;
- Accelerator volume_mute_;
- Accelerator volume_down_;
- Accelerator volume_up_;
- Accelerator previous_source_;
- Accelerator next_source_;
-
- bool IsModifier(unsigned int keysym) const;
- unsigned int ToModifier(unsigned int keysym) const;
-
- void MaybeDisableAccelerator(bool is_press,
- unsigned int keysym,
- unsigned int modifiers,
- Accelerator& accelerator) const;
-
- bool IsMatch(bool is_press,
- unsigned int keysym,
- unsigned int modifiers,
- Accelerator const& accelerator) const;
-
- void OnKeyDown(unsigned long event,
- unsigned long keysym,
- unsigned long state,
- const char* text,
- unsigned short repeat);
-
- void OnKeyUp(unsigned int keysym,
- unsigned long keycode,
- unsigned long state);
-
- /* This is just for telling an indicator to do something. */
- void ActivateIndicatorAction(std::string const& bus_name,
- std::string const& object_path,
- std::string const& action,
- glib::Variant const& parameter = glib::Variant()) const;
-
- void ActivateKeyboardAction(std::string const& action, glib::Variant const& parameter = glib::Variant()) const;
- void ActivateSoundAction(std::string const& action, glib::Variant const& parameter = glib::Variant()) const;
+ bool activate_panel_;
};
} // lockscreen namespace
diff --git a/lockscreen/LockScreenShield.cpp b/lockscreen/LockScreenShield.cpp
index 77c74ce1b..f04df87ac 100644
--- a/lockscreen/LockScreenShield.cpp
+++ b/lockscreen/LockScreenShield.cpp
@@ -36,8 +36,8 @@ namespace unity
namespace lockscreen
{
-Shield::Shield(session::Manager::Ptr const& session_manager, indicator::Indicators::Ptr const& indicators, int monitor_num, bool is_primary)
- : AbstractShield(session_manager, indicators, monitor_num, is_primary)
+Shield::Shield(session::Manager::Ptr const& session_manager, indicator::Indicators::Ptr const& indicators, Accelerators::Ptr const& accelerators, int monitor_num, bool is_primary)
+ : AbstractShield(session_manager, indicators, accelerators, monitor_num, is_primary)
, bg_settings_(std::make_shared<BackgroundSettings>())
, prompt_view_(nullptr)
, panel_view_(nullptr)
@@ -177,14 +177,25 @@ UserPromptView* Shield::CreatePromptView()
return prompt_view;
}
-nux::Area* Shield::FindKeyFocusArea(unsigned etype, unsigned long key_sym, unsigned long modifiers)
+nux::Area* Shield::FindKeyFocusArea(unsigned etype, unsigned long keysym, unsigned long modifiers)
{
if (primary)
{
- grab_key.emit(modifiers, key_sym);
+ grab_key.emit(modifiers, keysym);
- if (panel_view_ && panel_view_->WillHandleKeyEvent(etype, key_sym, modifiers))
- return panel_view_;
+ if (accelerators_)
+ {
+ if (etype == nux::EVENT_KEY_DOWN)
+ {
+ if (accelerators_->HandleKeyPress(keysym, modifiers))
+ return panel_view_;
+ }
+ else if (etype == nux::EVENT_KEY_UP)
+ {
+ if (accelerators_->HandleKeyRelease(keysym, modifiers))
+ return panel_view_;
+ }
+ }
if (prompt_view_)
{
@@ -218,5 +229,11 @@ bool Shield::IsIndicatorOpen() const
return panel_view_ ? panel_view_->active() : false;
}
+void Shield::ActivatePanel()
+{
+ if (panel_view_)
+ panel_view_->ActivatePanel();
+}
+
}
}
diff --git a/lockscreen/LockScreenShield.h b/lockscreen/LockScreenShield.h
index ec63e50e7..62a6634ba 100644
--- a/lockscreen/LockScreenShield.h
+++ b/lockscreen/LockScreenShield.h
@@ -36,10 +36,11 @@ class Panel;
class Shield : public AbstractShield
{
public:
- Shield(session::Manager::Ptr const&, indicator::Indicators::Ptr const&, int monitor, bool is_primary);
+ Shield(session::Manager::Ptr const&, indicator::Indicators::Ptr const&, Accelerators::Ptr const&, int monitor, bool is_primary);
bool IsIndicatorOpen() const override;
void CheckCapsLockPrompt() override;
+ void ActivatePanel() override;
protected:
bool AcceptKeyNavFocus() override;
diff --git a/lockscreen/LockScreenShieldFactory.cpp b/lockscreen/LockScreenShieldFactory.cpp
index 4932ca5c4..6bed3db27 100644
--- a/lockscreen/LockScreenShieldFactory.cpp
+++ b/lockscreen/LockScreenShieldFactory.cpp
@@ -25,9 +25,9 @@ namespace unity
namespace lockscreen
{
-nux::ObjectPtr<AbstractShield> ShieldFactory::CreateShield(session::Manager::Ptr const& session_manager, indicator::Indicators::Ptr const& indicators, int monitor, bool is_primary)
+nux::ObjectPtr<AbstractShield> ShieldFactory::CreateShield(session::Manager::Ptr const& session_manager, indicator::Indicators::Ptr const& indicators, Accelerators::Ptr const& accelerators, int monitor, bool is_primary)
{
- return nux::ObjectPtr<Shield>(new Shield(session_manager, indicators, monitor, is_primary));
+ return nux::ObjectPtr<Shield>(new Shield(session_manager, indicators, accelerators, monitor, is_primary));
}
}
diff --git a/lockscreen/LockScreenShieldFactory.h b/lockscreen/LockScreenShieldFactory.h
index 19b3894fa..581feba9f 100644
--- a/lockscreen/LockScreenShieldFactory.h
+++ b/lockscreen/LockScreenShieldFactory.h
@@ -37,12 +37,12 @@ struct ShieldFactoryInterface
virtual ~ShieldFactoryInterface() = default;
- virtual nux::ObjectPtr<AbstractShield> CreateShield(session::Manager::Ptr const&, indicator::Indicators::Ptr const&, int monitor, bool is_primary) = 0;
+ virtual nux::ObjectPtr<AbstractShield> CreateShield(session::Manager::Ptr const&, indicator::Indicators::Ptr const&, Accelerators::Ptr const&, int monitor, bool is_primary) = 0;
};
struct ShieldFactory : ShieldFactoryInterface
{
- nux::ObjectPtr<AbstractShield> CreateShield(session::Manager::Ptr const&, indicator::Indicators::Ptr const&, int monitor, bool is_primary) override;
+ nux::ObjectPtr<AbstractShield> CreateShield(session::Manager::Ptr const&, indicator::Indicators::Ptr const&, Accelerators::Ptr const&, int monitor, bool is_primary) override;
};
}
diff --git a/tests/test_lockscreen_controller.cpp b/tests/test_lockscreen_controller.cpp
index 55add06bc..fc54b7153 100644
--- a/tests/test_lockscreen_controller.cpp
+++ b/tests/test_lockscreen_controller.cpp
@@ -52,16 +52,17 @@ const unsigned TICK_DURATION = 10 * 1000;
struct MockShield : AbstractShield
{
MockShield()
- : AbstractShield(nullptr, nullptr, 0, false)
+ : AbstractShield(nullptr, nullptr, nullptr, 0, false)
{}
MOCK_CONST_METHOD0(IsIndicatorOpen, bool());
MOCK_METHOD0(CheckCapsLockPrompt, void());
+ MOCK_METHOD0(ActivatePanel, void());
};
struct ShieldFactoryMock : ShieldFactoryInterface
{
- nux::ObjectPtr<AbstractShield> CreateShield(session::Manager::Ptr const&, indicator::Indicators::Ptr const&, int, bool) override
+ nux::ObjectPtr<AbstractShield> CreateShield(session::Manager::Ptr const&, indicator::Indicators::Ptr const&, Accelerators::Ptr const&, int, bool) override
{
return nux::ObjectPtr<AbstractShield>(new MockShield());
}