Merge lp:~attente/indicator-keyboard/switch-layout-on-lock into lp:indicator-keyboard

Proposed by William Hua
Status: Merged
Approved by: Ted Gould
Approved revision: 336
Merged at revision: 339
Proposed branch: lp:~attente/indicator-keyboard/switch-layout-on-lock
Merge into: lp:indicator-keyboard
Prerequisite: lp:~attente/indicator-keyboard/1291962-2
Diff against target: 525 lines (+282/-30)
7 files modified
data/Makefile.am (+1/-1)
lib/Makefile.am (+9/-7)
lib/indicator-menu.vala (+23/-7)
lib/keyboard-plugin.vala (+23/-0)
lib/main.vala (+197/-10)
lib/unity-session.vala (+24/-0)
po/indicator-keyboard.pot (+5/-5)
To merge this branch: bzr merge lp:~attente/indicator-keyboard/switch-layout-on-lock
Reviewer Review Type Date Requested Status
Ted Gould (community) Approve
Lars Karlitski (community) Approve
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+215167@code.launchpad.net

This proposal supersedes a proposal from 2014-04-01.

Commit message

If an IBus input source is active when the session is locked, switch to another non-IBus one instead.

Description of the change

If an IBus input source is active when the session is locked, switch to another non-IBus one instead.

This depends on https://code.launchpad.net/~attente/unity-settings-daemon/activate-input-source/+merge/214219.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Ted Gould (ted) wrote : Posted in a previous version of this proposal

I don't think it's a good idea to update the current value in DConf based on going into the lock screen. For instance if the session was killed in some way (run out of battery) while the screen was locked, the value would end up being the lock screen value. It would be better to leave the saved session value in DConf and keep a different state in memory while the screen is locked.

review: Needs Fixing
Revision history for this message
William Hua (attente) wrote : Posted in a previous version of this proposal

That's a good point Ted. I'm proposing https://code.launchpad.net/~attente/unity-settings-daemon/activate-input-source/+merge/214219 (that this depends on) so that we have a way to update the current input source without having it persisted in dconf, as the setting and the state are tightly bound together in u-s-d. It also made this MP a lot bigger too unfortunately...

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
William Hua (attente) wrote : Posted in a previous version of this proposal

I think it failed because of a bad merge with trunk, hopefully ok now. Also, this has https://code.launchpad.net/~attente/indicator-keyboard/1291962-2/+merge/213346 merged into it, so it looks bigger than it should be.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
William Hua (attente) wrote : Posted in a previous version of this proposal

Merging 1291962-2 again in anticipation of conflicts with trunk.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Lars Karlitski (larsu) wrote :

Looks good to me now, thanks.

review: Approve
Revision history for this message
Ted Gould (ted) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'data/Makefile.am'
2--- data/Makefile.am 2014-04-10 12:57:57 +0000
3+++ data/Makefile.am 2014-04-10 12:57:57 +0000
4@@ -57,7 +57,7 @@
5 echo 'ObjectPath=/com/canonical/indicator/keyboard/desktop_greeter'; \
6 echo ''; \
7 echo '[desktop_lockscreen]'; \
8- echo 'ObjectPath=/com/canonical/indicator/keyboard/desktop_greeter'; \
9+ echo 'ObjectPath=/com/canonical/indicator/keyboard/desktop_lockscreen'; \
10 echo ''; \
11 echo '[ubiquity]'; \
12 echo 'ObjectPath=/com/canonical/indicator/keyboard/desktop') > $@.tmp && \
13
14=== modified file 'lib/Makefile.am'
15--- lib/Makefile.am 2014-04-10 12:57:57 +0000
16+++ lib/Makefile.am 2014-04-10 12:57:57 +0000
17@@ -6,13 +6,15 @@
18 --metadatadir $(top_srcdir)/deps \
19 --vapidir $(top_srcdir)/deps
20
21-indicator_keyboard_service_SOURCES = main.vala \
22- source.vala \
23- common.vala \
24- ibus-menu.vala \
25- ibus-panel.vala \
26- indicator-menu.vala \
27- window-stack.vala \
28+indicator_keyboard_service_SOURCES = main.vala \
29+ source.vala \
30+ common.vala \
31+ ibus-menu.vala \
32+ ibus-panel.vala \
33+ indicator-menu.vala \
34+ keyboard-plugin.vala \
35+ window-stack.vala \
36+ unity-session.vala \
37 unity-greeter.vala
38 indicator_keyboard_service_VALAFLAGS = $(AM_VALAFLAGS) \
39 --pkg gee-1.0 \
40
41=== modified file 'lib/indicator-menu.vala'
42--- lib/indicator-menu.vala 2014-04-10 12:57:57 +0000
43+++ lib/indicator-menu.vala 2014-04-10 12:57:57 +0000
44@@ -20,8 +20,9 @@
45
46 public enum Options {
47 NONE = 0x0,
48- IBUS = 0x1,
49- SETTINGS = 0x2
50+ DCONF = 0x1,
51+ IBUS = 0x2,
52+ SETTINGS = 0x4
53 }
54
55 private Options options;
56@@ -30,7 +31,7 @@
57 private Menu sources_section;
58 private IBusMenu properties_section;
59
60- public IndicatorMenu (ActionMap? action_map = null, Options options = Options.IBUS | Options.SETTINGS) {
61+ public IndicatorMenu (ActionMap? action_map = null, Options options = Options.NONE) {
62 var submenu = new Menu ();
63
64 sources_section = new Menu ();
65@@ -51,10 +52,17 @@
66 }
67
68 var indicator = new MenuItem.submenu (null, submenu);
69+ indicator.set_detailed_action ("indicator.indicator");
70 indicator.set_attribute ("x-canonical-type", "s", "com.canonical.indicator.root");
71- indicator.set_attribute ("x-canonical-secondary-action", "s", "indicator.next");
72- indicator.set_attribute ("x-canonical-scroll-action", "s", "indicator.scroll");
73- indicator.set_detailed_action ("indicator.indicator");
74+
75+ /* We need special mouse actions on the lock screen. */
76+ if ((options & Options.DCONF) != Options.NONE) {
77+ indicator.set_attribute ("x-canonical-secondary-action", "s", "indicator.next");
78+ indicator.set_attribute ("x-canonical-scroll-action", "s", "indicator.scroll");
79+ } else {
80+ indicator.set_attribute ("x-canonical-secondary-action", "s", "indicator.locked_next");
81+ indicator.set_attribute ("x-canonical-scroll-action", "s", "indicator.locked_scroll");
82+ }
83
84 indicator_menu = new Menu ();
85 indicator_menu.append_item (indicator);
86@@ -69,7 +77,15 @@
87
88 for (var i = 0; i < sources.length; i++) {
89 if (!sources[i].is_ibus || (options & Options.IBUS) != Options.NONE) {
90- var item = new MenuItem (sources[i].name, "indicator.current");
91+ string action;
92+
93+ if ((options & Options.DCONF) != Options.NONE) {
94+ action = "indicator.current";
95+ } else {
96+ action = "indicator.active";
97+ }
98+
99+ var item = new MenuItem (sources[i].name, action);
100
101 item.set_attribute (Menu.ATTRIBUTE_TARGET, "u", i);
102
103
104=== added file 'lib/keyboard-plugin.vala'
105--- lib/keyboard-plugin.vala 1970-01-01 00:00:00 +0000
106+++ lib/keyboard-plugin.vala 2014-04-10 12:57:57 +0000
107@@ -0,0 +1,23 @@
108+/*
109+ * Copyright 2014 Canonical Ltd.
110+ *
111+ * This program is free software: you can redistribute it and/or modify
112+ * it under the terms of the GNU General Public License as published by
113+ * the Free Software Foundation, version 3 of the License.
114+ *
115+ * This program is distributed in the hope that it will be useful,
116+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
117+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
118+ * GNU General Public License for more details.
119+ *
120+ * You should have received a copy of the GNU General Public License
121+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
122+ *
123+ * Authors: William Hua <william.hua@canonical.com>
124+ */
125+
126+[DBus (name="com.canonical.SettingsDaemon.Keyboard.Private")]
127+public interface KeyboardPlugin : Object {
128+
129+ public abstract void activate_input_source (uint index) throws IOError;
130+}
131
132=== modified file 'lib/main.vala'
133--- lib/main.vala 2014-04-10 12:57:57 +0000
134+++ lib/main.vala 2014-04-10 12:57:57 +0000
135@@ -45,9 +45,13 @@
136
137 private SimpleActionGroup? action_group;
138 private SimpleAction? indicator_action;
139+ private SimpleAction? active_action;
140 private IndicatorMenu? desktop_menu;
141 private IndicatorMenu? desktop_greeter_menu;
142+ private IndicatorMenu? desktop_lockscreen_menu;
143
144+ private KeyboardPlugin? keyboard_plugin;
145+ private UnitySession? unity_session;
146 private UnityGreeter? unity_greeter;
147 private string? greeter_user;
148 private uint lightdm_current;
149@@ -78,6 +82,10 @@
150 get_desktop_greeter_menu ().set_sources (get_sources ());
151 }
152
153+ if (desktop_lockscreen_menu != null) {
154+ get_desktop_lockscreen_menu ().set_sources (get_sources ());
155+ }
156+
157 if (indicator_action != null) {
158 update_indicator_action ();
159 }
160@@ -99,6 +107,18 @@
161 }
162 } else {
163 Bus.watch_name (BusType.SESSION,
164+ "org.gnome.SettingsDaemon.Keyboard",
165+ BusNameWatcherFlags.NONE,
166+ handle_keyboard_name_appeared,
167+ handle_keyboard_name_vanished);
168+
169+ Bus.watch_name (BusType.SESSION,
170+ "com.canonical.Unity",
171+ BusNameWatcherFlags.NONE,
172+ handle_unity_name_appeared,
173+ handle_unity_name_vanished);
174+
175+ Bus.watch_name (BusType.SESSION,
176 "com.canonical.Unity.WindowStack",
177 BusNameWatcherFlags.NONE,
178 handle_window_stack_name_appeared,
179@@ -139,6 +159,10 @@
180 get_desktop_greeter_menu ().set_sources (get_sources ());
181 }
182
183+ if (desktop_lockscreen_menu != null) {
184+ get_desktop_lockscreen_menu ().set_sources (get_sources ());
185+ }
186+
187 if (indicator_action != null) {
188 update_indicator_action ();
189 }
190@@ -665,20 +689,19 @@
191
192 [DBus (visible = false)]
193 private void update_indicator_action () {
194- var visible = indicator_settings.get_boolean ("visible");
195- var current = source_settings.get_uint ("current");
196- var sources = get_sources ();
197-
198 Icon? icon = null;
199 string? name = null;
200
201- if (current < sources.length) {
202- icon = sources[current].icon;
203- name = sources[current].name;
204+ var sources = get_sources ();
205+ var active = get_active_action ().get_state ().get_uint32 ();
206+
207+ if (active < sources.length) {
208+ icon = sources[active].icon;
209+ name = sources[active].name;
210 }
211
212 var builder = new VariantBuilder (new VariantType ("a{sv}"));
213- builder.add ("{sv}", "visible", new Variant.boolean (visible));
214+ builder.add ("{sv}", "visible", indicator_settings.get_value ("visible"));
215 if (name != null) {
216 var description = _ ("%s input source").printf ((!) name);
217 builder.add ("{sv}", "accessible-desc", new Variant.string (description));
218@@ -702,6 +725,42 @@
219 }
220
221 [DBus (visible = false)]
222+ private void handle_changed_active (Variant? value) {
223+ if (value != null) {
224+ ((!) active_action).set_state ((!) value);
225+ update_indicator_action ();
226+
227+ if (keyboard_plugin != null) {
228+ try {
229+ ((!) keyboard_plugin).activate_input_source (((!) value).get_uint32 ());
230+ } catch (IOError error) {
231+ warning ("error: %s", error.message);
232+ }
233+ }
234+ }
235+ }
236+
237+ [DBus (visible = false)]
238+ private void update_active_action () {
239+ if (active_action != null) {
240+ ((!) active_action).set_state (source_settings.get_value ("current"));
241+ update_indicator_action ();
242+ }
243+ }
244+
245+ [DBus (visible = false)]
246+ private Action get_active_action () {
247+ if (active_action == null) {
248+ var current = source_settings.get_value ("current");
249+ active_action = new SimpleAction.stateful ("active", VariantType.UINT32, current);
250+ ((!) active_action).activate.connect ((parameter) => { ((!) active_action).change_state (parameter); });
251+ ((!) active_action).change_state.connect (handle_changed_active);
252+ }
253+
254+ return (!) active_action;
255+ }
256+
257+ [DBus (visible = false)]
258 private void handle_middle_click (Variant? parameter) {
259 handle_scroll_wheel (new Variant.int32 (-1));
260 }
261@@ -721,10 +780,62 @@
262 }
263
264 [DBus (visible = false)]
265+ private void handle_middle_click_when_locked (Variant? parameter) {
266+ handle_scroll_wheel_when_locked (new Variant.int32 (-1));
267+ }
268+
269+ [DBus (visible = false)]
270+ private void handle_scroll_wheel_when_locked (Variant? parameter) {
271+ if (parameter != null) {
272+ var sources = get_sources ();
273+ var non_ibus_length = 0;
274+
275+ /* Figure out how many non-IBus sources we have. */
276+ foreach (var source in sources) {
277+ if (!source.is_ibus) {
278+ non_ibus_length++;
279+ }
280+ }
281+
282+ if (non_ibus_length > 1) {
283+ var active_action = get_active_action ();
284+ var active = active_action.state.get_uint32 ();
285+ var offset = -((!) parameter).get_int32 () % non_ibus_length;
286+
287+ /* Make offset positive modulo non_ibus_length. */
288+ if (offset < 0) {
289+ offset += non_ibus_length;
290+ }
291+
292+ /* We need to cycle through non-IBus sources only. */
293+ while (offset > 0) {
294+ do {
295+ active = (active + 1) % sources.length;
296+ } while (sources[active].is_ibus);
297+
298+ offset--;
299+ }
300+
301+ active_action.change_state (new Variant.uint32 (active));
302+ }
303+ }
304+ }
305+
306+ [DBus (visible = false)]
307 protected virtual SimpleActionGroup create_action_group (Action root_action) {
308 var group = new SimpleActionGroup ();
309
310+ /*
311+ * The 'current' action reflects the current setting in
312+ * GSettings and the 'active' action only exists to set the
313+ * active input source without persisting it.
314+ *
315+ * The lock screen menu uses the 'active' action while the
316+ * other menus instead persist the current input source.
317+ */
318+
319 group.add_action (root_action);
320+ group.add_action (get_active_action ());
321 group.add_action (source_settings.create_action ("current"));
322
323 var action = new SimpleAction ("next", null);
324@@ -735,6 +846,14 @@
325 action.activate.connect (handle_scroll_wheel);
326 group.add_action (action);
327
328+ action = new SimpleAction ("locked_next", null);
329+ action.activate.connect (handle_middle_click_when_locked);
330+ group.add_action (action);
331+
332+ action = new SimpleAction ("locked_scroll", VariantType.INT32);
333+ action.activate.connect (handle_scroll_wheel_when_locked);
334+ group.add_action (action);
335+
336 action = new SimpleAction ("map", null);
337 action.activate.connect (handle_activate_map);
338 group.add_action (action);
339@@ -762,7 +881,11 @@
340 [DBus (visible = false)]
341 public IndicatorMenu get_desktop_menu () {
342 if (desktop_menu == null) {
343- desktop_menu = new IndicatorMenu (get_action_group ());
344+ var options = IndicatorMenu.Options.DCONF
345+ | IndicatorMenu.Options.IBUS
346+ | IndicatorMenu.Options.SETTINGS;
347+
348+ desktop_menu = new IndicatorMenu (get_action_group (), options);
349 ((!) desktop_menu).set_sources (get_sources ());
350 ((!) desktop_menu).activate.connect ((property, state) => {
351 var panel = get_ibus_panel ();
352@@ -783,7 +906,9 @@
353 [DBus (visible = false)]
354 public IndicatorMenu get_desktop_greeter_menu () {
355 if (desktop_greeter_menu == null) {
356- desktop_greeter_menu = new IndicatorMenu (get_action_group (), IndicatorMenu.Options.NONE);
357+ var options = IndicatorMenu.Options.DCONF;
358+
359+ desktop_greeter_menu = new IndicatorMenu (get_action_group (), options);
360 ((!) desktop_greeter_menu).set_sources (get_sources ());
361 }
362
363@@ -791,6 +916,18 @@
364 }
365
366 [DBus (visible = false)]
367+ public IndicatorMenu get_desktop_lockscreen_menu () {
368+ if (desktop_lockscreen_menu == null) {
369+ var options = IndicatorMenu.Options.NONE;
370+
371+ desktop_lockscreen_menu = new IndicatorMenu (get_action_group (), options);
372+ ((!) desktop_lockscreen_menu).set_sources (get_sources ());
373+ }
374+
375+ return (!) desktop_lockscreen_menu;
376+ }
377+
378+ [DBus (visible = false)]
379 private void handle_changed_visible (string key) {
380 update_indicator_action ();
381 }
382@@ -798,6 +935,7 @@
383 [DBus (visible = false)]
384 private void handle_changed_current (string key) {
385 update_indicator_action ();
386+ update_active_action ();
387 update_login_layout ();
388 }
389
390@@ -807,6 +945,7 @@
391
392 get_desktop_menu ().set_sources (get_sources ());
393 get_desktop_greeter_menu ().set_sources (get_sources ());
394+ get_desktop_lockscreen_menu ().set_sources (get_sources ());
395 update_indicator_action ();
396 update_login_layout ();
397 }
398@@ -878,6 +1017,53 @@
399 }
400
401 [DBus (visible = false)]
402+ private void handle_keyboard_name_appeared (DBusConnection connection, string name, string name_owner) {
403+ try {
404+ keyboard_plugin = Bus.get_proxy_sync (BusType.SESSION, name, "/org/gnome/SettingsDaemon/Keyboard");
405+ } catch (IOError error) {
406+ warning ("error: %s", error.message);
407+ }
408+ }
409+
410+ [DBus (visible = false)]
411+ private void handle_keyboard_name_vanished (DBusConnection connection, string name) {
412+ keyboard_plugin = null;
413+ }
414+
415+ [DBus (visible = false)]
416+ private void handle_unity_name_appeared (DBusConnection connection, string name, string name_owner) {
417+ try {
418+ unity_session = Bus.get_proxy_sync (BusType.SESSION, name, "/com/canonical/Unity/Session");
419+ ((!) unity_session).locked.connect (() => {
420+ var sources = get_sources ();
421+
422+ if (sources.length > 0) {
423+ var current = source_settings.get_uint ("current");
424+
425+ if (current < sources.length && sources[current].is_ibus) {
426+ for (var i = 0; i < sources.length; i++) {
427+ if (!sources[i].is_ibus) {
428+ get_active_action ().change_state (new Variant.uint32 (i));
429+ break;
430+ }
431+ }
432+ }
433+ }
434+ });
435+ ((!) unity_session).unlocked.connect (() => {
436+ get_active_action ().change_state (source_settings.get_value ("current"));
437+ });
438+ } catch (IOError error) {
439+ warning ("error: %s", error.message);
440+ }
441+ }
442+
443+ [DBus (visible = false)]
444+ private void handle_unity_name_vanished (DBusConnection connection, string name) {
445+ unity_session = null;
446+ }
447+
448+ [DBus (visible = false)]
449 private void handle_window_stack_name_appeared (DBusConnection connection, string name, string name_owner) {
450 try {
451 window_stack = Bus.get_proxy_sync (BusType.SESSION, name, "/com/canonical/Unity/WindowStack");
452@@ -898,6 +1084,7 @@
453 connection.export_action_group ("/com/canonical/indicator/keyboard", get_action_group ());
454 connection.export_menu_model ("/com/canonical/indicator/keyboard/desktop", get_desktop_menu ());
455 connection.export_menu_model ("/com/canonical/indicator/keyboard/desktop_greeter", get_desktop_greeter_menu ());
456+ connection.export_menu_model ("/com/canonical/indicator/keyboard/desktop_lockscreen", get_desktop_lockscreen_menu ());
457 } catch (Error error) {
458 warning ("error: %s", error.message);
459 }
460
461=== added file 'lib/unity-session.vala'
462--- lib/unity-session.vala 1970-01-01 00:00:00 +0000
463+++ lib/unity-session.vala 2014-04-10 12:57:57 +0000
464@@ -0,0 +1,24 @@
465+/*
466+ * Copyright 2014 Canonical Ltd.
467+ *
468+ * This program is free software: you can redistribute it and/or modify
469+ * it under the terms of the GNU General Public License as published by
470+ * the Free Software Foundation, version 3 of the License.
471+ *
472+ * This program is distributed in the hope that it will be useful,
473+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
474+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
475+ * GNU General Public License for more details.
476+ *
477+ * You should have received a copy of the GNU General Public License
478+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
479+ *
480+ * Authors: William Hua <william.hua@canonical.com>
481+ */
482+
483+[DBus (name="com.canonical.Unity.Session")]
484+public interface UnitySession : Object {
485+
486+ public signal void locked ();
487+ public signal void unlocked ();
488+}
489
490=== modified file 'po/indicator-keyboard.pot'
491--- po/indicator-keyboard.pot 2014-04-10 12:57:57 +0000
492+++ po/indicator-keyboard.pot 2014-04-10 12:57:57 +0000
493@@ -8,7 +8,7 @@
494 msgstr ""
495 "Project-Id-Version: PACKAGE VERSION\n"
496 "Report-Msgid-Bugs-To: \n"
497-"POT-Creation-Date: 2014-03-27 23:39+1300\n"
498+"POT-Creation-Date: 2014-04-05 11:53+1300\n"
499 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
500 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
501 "Language-Team: LANGUAGE <LL@li.org>\n"
502@@ -17,19 +17,19 @@
503 "Content-Type: text/plain; charset=CHARSET\n"
504 "Content-Transfer-Encoding: 8bit\n"
505
506-#: ../lib/main.vala:670
507+#: ../lib/main.vala:706
508 #, c-format
509 msgid "%s input source"
510 msgstr ""
511
512-#: ../lib/indicator-menu.vala:47
513+#: ../lib/indicator-menu.vala:48
514 msgid "Character Map"
515 msgstr ""
516
517-#: ../lib/indicator-menu.vala:48
518+#: ../lib/indicator-menu.vala:49
519 msgid "Keyboard Layout Chart"
520 msgstr ""
521
522-#: ../lib/indicator-menu.vala:49
523+#: ../lib/indicator-menu.vala:50
524 msgid "Text Entry Settings..."
525 msgstr ""

Subscribers

People subscribed via source and target branches

to all changes: