diff options
| author | William Hua <william.hua@canonical.com> | 2014-04-18 01:08:05 +1200 |
|---|---|---|
| committer | William Hua <william.hua@canonical.com> | 2014-04-18 01:08:05 +1200 |
| commit | 37fc8ba650ee6f212f037acb7795868772b5ce84 (patch) | |
| tree | 6d17849184af3152e86d0eee16f386bd2414dc1b | |
| parent | f7e3e1d0ad86546879981ebeeceb18902fe1bb55 (diff) | |
Rip everything out and start anew.
(bzr r3781.3.2)
| -rw-r--r-- | lockscreen/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | lockscreen/LockScreenAbstractShield.h | 6 | ||||
| -rw-r--r-- | lockscreen/LockScreenAccelerators.cpp | 468 | ||||
| -rw-r--r-- | lockscreen/LockScreenAccelerators.h | 94 | ||||
| -rw-r--r-- | lockscreen/LockScreenController.cpp | 133 | ||||
| -rw-r--r-- | lockscreen/LockScreenController.h | 5 | ||||
| -rw-r--r-- | lockscreen/LockScreenPanel.cpp | 581 | ||||
| -rw-r--r-- | lockscreen/LockScreenPanel.h | 73 | ||||
| -rw-r--r-- | lockscreen/LockScreenShield.cpp | 29 | ||||
| -rw-r--r-- | lockscreen/LockScreenShield.h | 3 | ||||
| -rw-r--r-- | lockscreen/LockScreenShieldFactory.cpp | 4 | ||||
| -rw-r--r-- | lockscreen/LockScreenShieldFactory.h | 4 | ||||
| -rw-r--r-- | tests/test_lockscreen_controller.cpp | 5 |
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(), >k_keysym, >k_keycodes, >k_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(), >k_keysym, >k_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()); } |
