Merge lp:~attente/unity/enable-sound-buttons-on-lock-screen into lp:unity

Proposed by William Hua
Status: Merged
Approved by: Marco Trevisan (Treviño)
Approved revision: no longer in the source branch.
Merged at revision: 3778
Proposed branch: lp:~attente/unity/enable-sound-buttons-on-lock-screen
Merge into: lp:unity
Diff against target: 398 lines (+289/-16)
4 files modified
lockscreen/LockScreenPanel.cpp (+233/-1)
lockscreen/LockScreenPanel.h (+51/-1)
lockscreen/LockScreenShield.cpp (+5/-11)
plugins/unityshell/src/unityshell.cpp (+0/-3)
To merge this branch: bzr merge lp:~attente/unity/enable-sound-buttons-on-lock-screen
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Marco Trevisan (Treviño) Approve
Review via email: mp+215194@code.launchpad.net

Commit message

Enable sound buttons and input source switching under lock screen.

Description of the change

Enable sound buttons and input source switching under lock screen.

This depends on this MP (for the input source switching to work properly): https://code.launchpad.net/~attente/indicator-keyboard/switch-layout-on-lock/+merge/215167

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

Thanks, looks good!

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lockscreen/LockScreenPanel.cpp'
2--- lockscreen/LockScreenPanel.cpp 2014-03-07 19:02:25 +0000
3+++ lockscreen/LockScreenPanel.cpp 2014-04-10 16:49:38 +0000
4@@ -21,6 +21,7 @@
5
6 #include <boost/algorithm/string/trim.hpp>
7 #include <Nux/HLayout.h>
8+#include <UnityCore/Variant.h>
9
10 #include "LockScreenSettings.h"
11 #include "panel/PanelIndicatorsView.h"
12@@ -38,6 +39,30 @@
13 namespace
14 {
15 const RawPixel PADDING = 5_em;
16+
17+const std::string MEDIA_KEYS_SCHEMA = "org.gnome.settings-daemon.plugins.media-keys";
18+const std::string MEDIA_KEYS_VOLUME_MUTE = "volume-mute";
19+const std::string MEDIA_KEYS_VOLUME_DOWN = "volume-down";
20+const std::string MEDIA_KEYS_VOLUME_UP = "volume-up";
21+const std::string INPUT_SWITCH_SCHEMA = "org.gnome.desktop.wm.keybindings";
22+const std::string INPUT_SWITCH_PREVIOUS = "switch-input-source-backward";
23+const std::string INPUT_SWITCH_NEXT = "switch-input-source";
24+
25+const std::string INDICATOR_KEYBOARD_BUS_NAME = "com.canonical.indicator.keyboard";
26+const std::string INDICATOR_KEYBOARD_OBJECT_PATH = "/com/canonical/indicator/keyboard";
27+const std::string INDICATOR_SOUND_BUS_NAME = "com.canonical.indicator.sound";
28+const std::string INDICATOR_SOUND_OBJECT_PATH = "/com/canonical/indicator/sound";
29+const std::string INDICATOR_ACTION_INTERFACE = "org.gtk.Actions";
30+
31+const std::string INDICATOR_KEYBOARD_ACTION_SCROLL = "locked_scroll";
32+const std::string INDICATOR_SOUND_ACTION_SCROLL = "scroll";
33+const std::string INDICATOR_SOUND_ACTION_MUTE = "mute";
34+
35+const unsigned int MODIFIERS = nux::KEY_MODIFIER_SHIFT |
36+ nux::KEY_MODIFIER_CAPS_LOCK |
37+ nux::KEY_MODIFIER_CTRL |
38+ nux::KEY_MODIFIER_ALT |
39+ nux::KEY_MODIFIER_SUPER;
40 }
41
42 using namespace indicator;
43@@ -49,6 +74,8 @@
44 , monitor(monitor_)
45 , indicators_(indicators)
46 , needs_geo_sync_(true)
47+ , media_key_settings_(g_settings_new(MEDIA_KEYS_SCHEMA.c_str()))
48+ , input_switch_settings_(g_settings_new(INPUT_SWITCH_SCHEMA.c_str()))
49 {
50 double scale = unity::Settings::Instance().em(monitor)->DPIScale();
51 auto* layout = new nux::HLayout();
52@@ -87,6 +114,11 @@
53 BuildTexture();
54 QueueRelayout();
55 });
56+
57+ ParseAccelerators();
58+
59+ key_down.connect(sigc::mem_fun(this, &Panel::OnKeyDown));
60+ key_up.connect(sigc::mem_fun(this, &Panel::OnKeyUp));
61 }
62
63 void Panel::BuildTexture()
64@@ -215,11 +247,211 @@
65 }
66 }
67
68+Panel::Accelerator Panel::ParseAcceleratorString(std::string const& string) const
69+{
70+ guint gtk_key;
71+ GdkModifierType gtk_modifiers;
72+ gtk_accelerator_parse(string.c_str(), &gtk_key, &gtk_modifiers);
73+
74+ unsigned int nux_key = gtk_key;
75+ unsigned int nux_modifiers = 0;
76+
77+ if (gtk_modifiers & GDK_SHIFT_MASK)
78+ nux_modifiers |= nux::KEY_MODIFIER_SHIFT;
79+ if (gtk_modifiers & GDK_LOCK_MASK)
80+ nux_modifiers |= nux::KEY_MODIFIER_CAPS_LOCK;
81+ if (gtk_modifiers & GDK_CONTROL_MASK)
82+ nux_modifiers |= nux::KEY_MODIFIER_CTRL;
83+ if (gtk_modifiers & GDK_MOD1_MASK)
84+ nux_modifiers |= nux::KEY_MODIFIER_ALT;
85+ if (gtk_modifiers & GDK_SUPER_MASK)
86+ nux_modifiers |= nux::KEY_MODIFIER_SUPER;
87+
88+ return std::make_pair(nux_modifiers, nux_key);
89+}
90+
91+void Panel::ParseAccelerators()
92+{
93+ activate_indicator_ = WindowManager::Default().activate_indicators_key();
94+ volume_mute_ = ParseAcceleratorString(glib::String(g_settings_get_string(media_key_settings_, MEDIA_KEYS_VOLUME_MUTE.c_str())));
95+ volume_down_ = ParseAcceleratorString(glib::String(g_settings_get_string(media_key_settings_, MEDIA_KEYS_VOLUME_DOWN.c_str())));
96+ volume_up_ = ParseAcceleratorString(glib::String(g_settings_get_string(media_key_settings_, MEDIA_KEYS_VOLUME_UP.c_str())));
97+
98+ auto variant = glib::Variant(g_settings_get_value(input_switch_settings_, INPUT_SWITCH_PREVIOUS.c_str()), glib::StealRef());
99+
100+ if (g_variant_n_children(variant) > 0)
101+ {
102+ const gchar *accelerator;
103+ g_variant_get_child(variant, 0, "&s", &accelerator);
104+ previous_source_ = ParseAcceleratorString(accelerator);
105+ }
106+ else
107+ previous_source_ = std::make_pair(0, 0);
108+
109+ variant = glib::Variant(g_settings_get_value(input_switch_settings_, INPUT_SWITCH_NEXT.c_str()), glib::StealRef());
110+
111+ if (g_variant_n_children(variant) > 0)
112+ {
113+ const gchar *accelerator;
114+ g_variant_get_child(variant, 0, "&s", &accelerator);
115+ next_source_ = ParseAcceleratorString(accelerator);
116+ }
117+ else
118+ next_source_ = std::make_pair(0, 0);
119+}
120+
121+bool Panel::WillHandleKeyEvent(unsigned int event_type, unsigned long key_sym, unsigned long modifiers)
122+{
123+ auto is_press = event_type == nux::EVENT_KEY_DOWN;
124+
125+ /* If we're just pressing a key, and no modifiers are pressed, then
126+ * we can start accepting new actions again. */
127+ if (is_press && (modifiers & MODIFIERS) == 0)
128+ last_action_ = std::make_pair(0, 0);
129+
130+ return IsMatch(is_press, key_sym, modifiers, activate_indicator_) ||
131+ IsMatch(is_press, key_sym, modifiers, volume_mute_) ||
132+ IsMatch(is_press, key_sym, modifiers, volume_down_) ||
133+ IsMatch(is_press, key_sym, modifiers, volume_up_) ||
134+ IsMatch(is_press, key_sym, modifiers, previous_source_) ||
135+ IsMatch(is_press, key_sym, modifiers, next_source_);
136+}
137+
138 bool Panel::InspectKeyEvent(unsigned int event_type, unsigned int keysym, const char*)
139 {
140- ActivateFirst();
141 return true;
142 }
143
144+bool Panel::IsMatch(bool is_press,
145+ unsigned int key_sym,
146+ unsigned int state,
147+ Accelerator const& accelerator) const
148+{
149+ /* Do the easy check, just compare key codes and modifiers.
150+ * TODO: Check permutations of modifier-only shortcuts. */
151+ return key_sym == accelerator.second && (state & MODIFIERS) == accelerator.first;
152+}
153+
154+void Panel::OnKeyDown(unsigned long event,
155+ unsigned long key_sym,
156+ unsigned long state,
157+ const char* text,
158+ unsigned short repeat)
159+{
160+ if (IsMatch(true, key_sym, state, activate_indicator_))
161+ {
162+ ActivateFirst();
163+ last_action_ = activate_indicator_;
164+ }
165+ else if (IsMatch(true, key_sym, state, volume_mute_))
166+ {
167+ ActivateSoundAction(INDICATOR_SOUND_ACTION_MUTE);
168+ last_action_ = volume_mute_;
169+ }
170+ else if (IsMatch(true, key_sym, state, volume_down_))
171+ {
172+ ActivateSoundAction(INDICATOR_SOUND_ACTION_SCROLL, g_variant_new_int32(-1));
173+ last_action_ = volume_down_;
174+ }
175+ else if (IsMatch(true, key_sym, state, volume_up_))
176+ {
177+ ActivateSoundAction(INDICATOR_SOUND_ACTION_SCROLL, g_variant_new_int32(+1));
178+ last_action_ = volume_up_;
179+ }
180+ else if (IsMatch(true, key_sym, state, previous_source_))
181+ {
182+ ActivateKeyboardAction(INDICATOR_KEYBOARD_ACTION_SCROLL, g_variant_new_int32(-1));
183+ last_action_ = previous_source_;
184+ }
185+ else if (IsMatch(true, key_sym, state, next_source_))
186+ {
187+ ActivateKeyboardAction(INDICATOR_KEYBOARD_ACTION_SCROLL, g_variant_new_int32(+1));
188+ last_action_ = next_source_;
189+ }
190+}
191+
192+void Panel::OnKeyUp(unsigned int key_sym,
193+ unsigned long key_code,
194+ unsigned long state)
195+{
196+ /* We only want to act if we didn't activate the action on key
197+ * down. Once we see the key up, we can start accepting actions
198+ * again. */
199+
200+ if (IsMatch(false, key_sym, state, activate_indicator_))
201+ {
202+ if (last_action_ != activate_indicator_)
203+ ActivateFirst();
204+
205+ last_action_ = std::make_pair(0, 0);
206+ }
207+ else if (IsMatch(false, key_sym, state, volume_mute_))
208+ {
209+ if (last_action_ != volume_mute_)
210+ ActivateSoundAction(INDICATOR_SOUND_ACTION_MUTE);
211+
212+ last_action_ = std::make_pair(0, 0);
213+ }
214+ else if (IsMatch(false, key_sym, state, volume_down_))
215+ {
216+ if (last_action_ != volume_down_)
217+ ActivateSoundAction(INDICATOR_SOUND_ACTION_SCROLL, g_variant_new_int32(-1));
218+
219+ last_action_ = std::make_pair(0, 0);
220+ }
221+ else if (IsMatch(false, key_sym, state, volume_up_))
222+ {
223+ if (last_action_ != volume_up_)
224+ ActivateSoundAction(INDICATOR_SOUND_ACTION_SCROLL, g_variant_new_int32(+1));
225+
226+ last_action_ = std::make_pair(0, 0);
227+ }
228+ else if (IsMatch(false, key_sym, state, previous_source_))
229+ {
230+ if (last_action_ != previous_source_)
231+ ActivateKeyboardAction(INDICATOR_KEYBOARD_ACTION_SCROLL, g_variant_new_int32(-1));
232+
233+ last_action_ = std::make_pair(0, 0);
234+ }
235+ else if (IsMatch(false, key_sym, state, next_source_))
236+ {
237+ if (last_action_ != next_source_)
238+ ActivateKeyboardAction(INDICATOR_KEYBOARD_ACTION_SCROLL, g_variant_new_int32(+1));
239+
240+ last_action_ = std::make_pair(0, 0);
241+ }
242+}
243+
244+void Panel::ActivateIndicatorAction(std::string const& bus_name,
245+ std::string const& object_path,
246+ std::string const& action,
247+ glib::Variant const& parameter) const
248+{
249+ GVariantBuilder builder;
250+
251+ g_variant_builder_init(&builder, G_VARIANT_TYPE("(sava{sv})"));
252+ g_variant_builder_add(&builder, "s", action.c_str());
253+
254+ if (parameter)
255+ g_variant_builder_add_parsed(&builder, "[%v]", (GVariant*) parameter);
256+ else
257+ g_variant_builder_add_parsed(&builder, "@av []");
258+
259+ g_variant_builder_add_parsed(&builder, "@a{sv} []");
260+
261+ auto proxy = std::make_shared<glib::DBusProxy>(bus_name, object_path, INDICATOR_ACTION_INTERFACE, G_BUS_TYPE_SESSION);
262+ proxy->CallBegin("Activate", g_variant_builder_end(&builder), [proxy] (GVariant*, glib::Error const&) {});
263+}
264+
265+void Panel::ActivateKeyboardAction(std::string const& action, glib::Variant const& parameter) const
266+{
267+ ActivateIndicatorAction(INDICATOR_KEYBOARD_BUS_NAME, INDICATOR_KEYBOARD_OBJECT_PATH, action, parameter);
268+}
269+
270+void Panel::ActivateSoundAction(std::string const& action, glib::Variant const& parameter) const
271+{
272+ ActivateIndicatorAction(INDICATOR_SOUND_BUS_NAME, INDICATOR_SOUND_OBJECT_PATH, action, parameter);
273+}
274+
275 }
276 }
277
278=== modified file 'lockscreen/LockScreenPanel.h'
279--- lockscreen/LockScreenPanel.h 2014-03-06 20:51:28 +0000
280+++ lockscreen/LockScreenPanel.h 2014-04-10 16:49:38 +0000
281@@ -22,8 +22,10 @@
282
283 #include <Nux/Nux.h>
284 #include <Nux/View.h>
285+#include <UnityCore/GLibDBusProxy.h>
286+#include <UnityCore/GLibSource.h>
287+#include <UnityCore/GLibWrapper.h>
288 #include <UnityCore/Indicators.h>
289-#include <UnityCore/GLibSource.h>
290 #include <UnityCore/SessionManager.h>
291
292 namespace unity
293@@ -44,6 +46,8 @@
294 nux::Property<bool> active;
295 nux::Property<int> monitor;
296
297+ bool WillHandleKeyEvent(unsigned int event_type, unsigned long key_sym, unsigned long modifiers);
298+
299 protected:
300 void Draw(nux::GraphicsEngine& GfxContext, bool force_draw) override;
301 bool InspectKeyEvent(unsigned int event_type, unsigned int keysym, const char*) override;
302@@ -67,6 +71,52 @@
303 bool needs_geo_sync_;
304 nux::Point tracked_pointer_pos_;
305 glib::Source::UniquePtr track_menu_pointer_timeout_;
306+
307+ glib::Object<GSettings> media_key_settings_;
308+ glib::Object<GSettings> input_switch_settings_;
309+
310+ typedef std::pair<unsigned int, unsigned int> Accelerator;
311+ Accelerator ParseAcceleratorString(std::string const& string) const;
312+
313+ void ParseAccelerators();
314+
315+ Accelerator activate_indicator_;
316+ Accelerator volume_mute_;
317+ Accelerator volume_down_;
318+ Accelerator volume_up_;
319+ Accelerator previous_source_;
320+ Accelerator next_source_;
321+
322+ /* We only want to activate the indicator on key press OR key
323+ * release, never both, so we'll need to keep track of the last
324+ * action that occurred. However, holding the keys down should
325+ * allow multiple activations, for example, when the volume
326+ * down button is held down. */
327+ Accelerator last_action_;
328+
329+ bool IsMatch(bool is_press,
330+ unsigned int key_sym,
331+ unsigned int modifiers,
332+ Accelerator const& accelerator) const;
333+
334+ void OnKeyDown(unsigned long event,
335+ unsigned long key_sym,
336+ unsigned long state,
337+ const char* text,
338+ unsigned short repeat);
339+
340+ void OnKeyUp(unsigned int key_sym,
341+ unsigned long key_code,
342+ unsigned long state);
343+
344+ /* This is just for telling an indicator to do something. */
345+ void ActivateIndicatorAction(std::string const& bus_name,
346+ std::string const& object_path,
347+ std::string const& action,
348+ glib::Variant const& parameter = glib::Variant()) const;
349+
350+ void ActivateKeyboardAction(std::string const& action, glib::Variant const& parameter = glib::Variant()) const;
351+ void ActivateSoundAction(std::string const& action, glib::Variant const& parameter = glib::Variant()) const;
352 };
353
354 } // lockscreen namespace
355
356=== modified file 'lockscreen/LockScreenShield.cpp'
357--- lockscreen/LockScreenShield.cpp 2014-04-09 01:11:47 +0000
358+++ lockscreen/LockScreenShield.cpp 2014-04-10 16:49:38 +0000
359@@ -171,20 +171,14 @@
360 return prompt_view;
361 }
362
363-nux::Area* Shield::FindKeyFocusArea(unsigned etype, unsigned long key_code, unsigned long modifiers)
364+nux::Area* Shield::FindKeyFocusArea(unsigned etype, unsigned long key_sym, unsigned long modifiers)
365 {
366 if (primary)
367 {
368- grab_key.emit(modifiers, key_code);
369-
370- if (panel_view_)
371- {
372- modifiers &= (nux::NUX_STATE_ALT | nux::NUX_STATE_CTRL | nux::NUX_STATE_SUPER | nux::NUX_STATE_SHIFT);
373- auto const& indicators_key = WindowManager::Default().activate_indicators_key();
374-
375- if (indicators_key.first == modifiers && indicators_key.second == key_code)
376- return panel_view_;
377- }
378+ grab_key.emit(modifiers, key_sym);
379+
380+ if (panel_view_ && panel_view_->WillHandleKeyEvent(etype, key_sym, modifiers))
381+ return panel_view_;
382
383 if (prompt_view_)
384 {
385
386=== modified file 'plugins/unityshell/src/unityshell.cpp'
387--- plugins/unityshell/src/unityshell.cpp 2014-04-09 19:44:08 +0000
388+++ plugins/unityshell/src/unityshell.cpp 2014-04-10 16:49:38 +0000
389@@ -1984,9 +1984,6 @@
390 ubus_manager_.SendMessage(UBUS_OVERLAY_CLOSE_REQUEST);
391 }
392
393- if (g_strcmp0(plugin, "scale") == 0)
394- g_print("Scale event %s\n",event);
395-
396 if (adapter.IsScaleActive() && g_strcmp0(plugin, "scale") == 0 &&
397 super_keypressed_)
398 {