diff options
Diffstat (limited to 'lib/main.vala')
-rw-r--r-- | lib/main.vala | 236 |
1 files changed, 183 insertions, 53 deletions
diff --git a/lib/main.vala b/lib/main.vala index 1cb3896c..41ff5ff7 100644 --- a/lib/main.vala +++ b/lib/main.vala @@ -33,7 +33,7 @@ public class Indicator.Keyboard.Service : Object { private SList<Act.User> users; private WindowStack? window_stack; - private Gee.HashMap<uint, uint>? window_sources; + private Gee.HashMap<uint, Source>? window_sources; private uint focused_window_id; private IBus.Bus? ibus; @@ -41,6 +41,8 @@ public class Indicator.Keyboard.Service : Object { private ulong ibus_connected_id; private uint panel_timeout; + private Fcitx.InputMethod? fcitx; + private Source[]? sources; private SimpleActionGroup? action_group; @@ -118,11 +120,13 @@ public class Indicator.Keyboard.Service : Object { handle_unity_name_appeared, handle_unity_name_vanished); - Bus.watch_name (BusType.SESSION, - "com.canonical.Unity.WindowStack", - BusNameWatcherFlags.NONE, - handle_window_stack_name_appeared, - handle_window_stack_name_vanished); + if (!is_fcitx_active ()) { + Bus.watch_name (BusType.SESSION, + "com.canonical.Unity.WindowStack", + BusNameWatcherFlags.NONE, + handle_window_stack_name_appeared, + handle_window_stack_name_vanished); + } } indicator_settings = new Settings ("com.canonical.indicator.keyboard"); @@ -146,6 +150,26 @@ public class Indicator.Keyboard.Service : Object { } [DBus (visible = false)] + private static bool is_ibus_active () { + if (is_login_user ()) { + return false; + } + + var module = Environment.get_variable ("GTK_IM_MODULE"); + return module != null && (!) module == "ibus"; + } + + [DBus (visible = false)] + private static bool is_fcitx_active () { + if (is_login_user ()) { + return false; + } + + var module = Environment.get_variable ("GTK_IM_MODULE"); + return module != null && (!) module == "fcitx"; + } + + [DBus (visible = false)] private IBus.Bus get_ibus () { if (ibus == null) { IBus.init (); @@ -210,6 +234,20 @@ public class Indicator.Keyboard.Service : Object { } [DBus (visible = false)] + private Fcitx.InputMethod? get_fcitx () { + if (is_fcitx_active () && fcitx == null) { + try { + fcitx = new Fcitx.InputMethod (BusType.SESSION, DBusProxyFlags.NONE, 0); + ((!) fcitx).notify["current-im"].connect ((pspec) => { handle_changed_current ("current"); }); + } catch (Error error) { + warning ("error: %s", error.message); + } + } + + return fcitx; + } + + [DBus (visible = false)] public void up () { if (loop == null) { loop = new MainLoop (); @@ -254,11 +292,9 @@ public class Indicator.Keyboard.Service : Object { Act.User? user = manager.get_user ((!) greeter_user); if (user != null && ((!) user).is_loaded) { - VariantIter outer; - VariantIter inner; + var outer = ((!) user).input_sources.iterator (); - var sources = ((!) user).input_sources; - sources.get ("aa{ss}", out outer); + VariantIter inner; while (outer.next ("a{ss}", out inner)) { unowned string key; @@ -340,7 +376,7 @@ public class Indicator.Keyboard.Service : Object { [DBus (visible = false)] private void migrate_keyboard_layouts () { if (is_login_user ()) { - lightdm_current = source_settings.get_uint ("current"); + lightdm_current = get_current (); var manager = Act.UserManager.get_default (); @@ -448,14 +484,11 @@ public class Indicator.Keyboard.Service : Object { foreach (var user in users) { if (user.is_loaded) { + var outer = user.input_sources.iterator (); var done = false; - VariantIter outer; VariantIter inner; - var sources = user.input_sources; - sources.get ("aa{ss}", out outer); - while (outer.next ("a{ss}", out inner)) { unowned string key; unowned string source; @@ -548,7 +581,7 @@ public class Indicator.Keyboard.Service : Object { private void update_login_layout () { if (is_login_user ()) { unowned List<LightDM.Layout> layouts = LightDM.get_layouts (); - var current = source_settings.get_uint ("current"); + var current = get_current (); if (current < get_sources ().length) { var source = get_sources ()[current]; @@ -594,10 +627,12 @@ public class Indicator.Keyboard.Service : Object { warning ("error: %s", error.message); } - window_sources = new Gee.HashMap<uint, uint> (); + window_sources = new Gee.HashMap<uint, Source> (); + ((!) window_stack).window_destroyed.connect (handle_window_destroyed); ((!) window_stack).focused_window_changed.connect (handle_focused_window_changed); } else { ((!) window_stack).focused_window_changed.disconnect (handle_focused_window_changed); + ((!) window_stack).window_destroyed.disconnect (handle_window_destroyed); window_sources = null; } } @@ -610,22 +645,49 @@ public class Indicator.Keyboard.Service : Object { } [DBus (visible = false)] + private void handle_window_destroyed (uint window_id, string app_id) { + ((!) window_sources).unset (window_id); + } + + [DBus (visible = false)] private void handle_focused_window_changed (uint window_id, string app_id, uint stage) { - var old_current = source_settings.get_uint ("current"); + var sources = get_sources (); + var old_current = get_current (); - ((!) window_sources)[focused_window_id] = old_current; + if (old_current < sources.length) { + ((!) window_sources)[focused_window_id] = sources[old_current]; + } if (!(((!) window_sources).has_key (window_id))) { var default_group = per_window_settings.get_int ("default-group"); - if (default_group >= 0 && default_group != old_current) { - source_settings.set_uint ("current", (uint) default_group); + if (default_group >= 0) { + for (var offset = 0; offset < sources.length; offset++) { + var current = (default_group + offset) % sources.length; + var source = sources[current]; + + if (source.is_xkb || + (source.is_ibus && is_ibus_active ()) || + (source.is_fcitx && is_fcitx_active ())) { + if (current != old_current) { + source_settings.set_uint ("current", current); + } + + break; + } + } } } else { - var current = ((!) window_sources)[window_id]; + var source = ((!) window_sources)[window_id]; - if (current != old_current) { - source_settings.set_uint ("current", current); + for (var current = 0; current < sources.length; current++) { + if (sources[current] == source) { + if (current != old_current) { + source_settings.set_uint ("current", current); + } + + break; + } } } @@ -633,6 +695,40 @@ public class Indicator.Keyboard.Service : Object { } [DBus (visible = false)] + private uint get_current () { + if (is_fcitx_active () && get_fcitx () != null) { + string? engine = ((!) get_fcitx ()).current_im; + + if (engine != null) { + var is_xkb = ((!) engine).has_prefix ("fcitx-keyboard-"); + var type = is_xkb ? "xkb" : "fcitx"; + var name = (!) engine; + + if (is_xkb) { + name = name.substring ("fcitx-keyboard-".length); + var index = name.index_of ("-"); + if (index >= 0) { + name.data[index] = '+'; + } + } + + var iter = source_settings.get_value ("sources").iterator (); + + unowned string source_type; + unowned string source_name; + + for (var i = 0; iter.next ("(&s&s)", out source_type, out source_name); i++) { + if (source_name == name && source_type == type) { + return i; + } + } + } + } + + return source_settings.get_uint ("current"); + } + + [DBus (visible = false)] private Source[] get_sources () { if (sources == null) { var array = source_settings.get_value ("sources"); @@ -743,7 +839,7 @@ public class Indicator.Keyboard.Service : Object { [DBus (visible = false)] private void update_active_action () { if (active_action != null) { - ((!) active_action).set_state (source_settings.get_value ("current")); + ((!) active_action).set_state (new Variant.uint32 (get_current ())); update_indicator_action (); } } @@ -751,8 +847,7 @@ public class Indicator.Keyboard.Service : Object { [DBus (visible = false)] private Action get_active_action () { if (active_action == null) { - var current = source_settings.get_value ("current"); - active_action = new SimpleAction.stateful ("active", VariantType.UINT32, current); + active_action = new SimpleAction.stateful ("active", VariantType.UINT32, new Variant.uint32 (get_current ())); ((!) active_action).activate.connect ((parameter) => { ((!) active_action).change_state (parameter); }); ((!) active_action).change_state.connect (handle_changed_active); } @@ -768,13 +863,41 @@ public class Indicator.Keyboard.Service : Object { [DBus (visible = false)] private void handle_scroll_wheel (Variant? parameter) { if (parameter != null) { - var sources = source_settings.get_value ("sources"); - var current = source_settings.get_uint ("current"); - var length = (int) sources.n_children (); + var old_current = get_current (); + var sources = get_sources (); + var length = 0; - if (length > 0) { - var offset = ((!) parameter).get_int32 () % length; - source_settings.set_uint ("current", (current + (length - offset)) % length); + foreach (var source in sources) { + if (source.is_xkb || + (source.is_ibus && is_ibus_active ()) || + (source.is_fcitx && is_fcitx_active ())) { + length++; + } + } + + if (length > 1) { + var current = old_current; + var offset = -((!) parameter).get_int32 () % length; + + /* Go backward. */ + for (; offset < 0; offset++) { + do { + current = (current + sources.length - 1) % sources.length; + } while ((sources[current].is_ibus && !is_ibus_active ()) || + (sources[current].is_fcitx && !is_fcitx_active ())); + } + + /* Go forward. */ + for (; offset > 0; offset--) { + do { + current = (current + 1) % sources.length; + } while ((sources[current].is_ibus && !is_ibus_active ()) || + (sources[current].is_fcitx && !is_fcitx_active ())); + } + + if (current != old_current) { + source_settings.set_uint ("current", current); + } } } } @@ -788,30 +911,30 @@ public class Indicator.Keyboard.Service : Object { private void handle_scroll_wheel_when_locked (Variant? parameter) { if (parameter != null) { var sources = get_sources (); - var non_ibus_length = 0; + var xkb_length = 0; - /* Figure out how many non-IBus sources we have. */ + /* Figure out how many Xkb sources we have. */ foreach (var source in sources) { - if (!source.is_ibus) { - non_ibus_length++; + if (source.is_xkb) { + xkb_length++; } } - if (non_ibus_length > 1) { + if (xkb_length > 1) { var active_action = get_active_action (); var active = active_action.get_state ().get_uint32 (); - var offset = -((!) parameter).get_int32 () % non_ibus_length; + var offset = -((!) parameter).get_int32 () % xkb_length; - /* Make offset positive modulo non_ibus_length. */ + /* Make offset positive modulo xkb_length. */ if (offset < 0) { - offset += non_ibus_length; + offset += xkb_length; } - /* We need to cycle through non-IBus sources only. */ + /* We need to cycle through Xkb sources only. */ while (offset > 0) { do { active = (active + 1) % sources.length; - } while (sources[active].is_ibus); + } while (!sources[active].is_xkb); offset--; } @@ -881,9 +1004,15 @@ public class Indicator.Keyboard.Service : Object { [DBus (visible = false)] public IndicatorMenu get_desktop_menu () { if (desktop_menu == null) { - var options = IndicatorMenu.Options.DCONF - | IndicatorMenu.Options.IBUS - | IndicatorMenu.Options.SETTINGS; + var options = IndicatorMenu.Options.DCONF; + + if (!is_fcitx_active ()) { + options |= IndicatorMenu.Options.XKB | IndicatorMenu.Options.SETTINGS; + + if (is_ibus_active ()) { + options |= IndicatorMenu.Options.IBUS; + } + } desktop_menu = new IndicatorMenu (get_action_group (), options); ((!) desktop_menu).set_sources (get_sources ()); @@ -906,7 +1035,8 @@ public class Indicator.Keyboard.Service : Object { [DBus (visible = false)] public IndicatorMenu get_desktop_greeter_menu () { if (desktop_greeter_menu == null) { - var options = IndicatorMenu.Options.DCONF; + var options = IndicatorMenu.Options.DCONF | + IndicatorMenu.Options.XKB; desktop_greeter_menu = new IndicatorMenu (get_action_group (), options); ((!) desktop_greeter_menu).set_sources (get_sources ()); @@ -918,7 +1048,7 @@ public class Indicator.Keyboard.Service : Object { [DBus (visible = false)] public IndicatorMenu get_desktop_lockscreen_menu () { if (desktop_lockscreen_menu == null) { - var options = IndicatorMenu.Options.NONE; + var options = IndicatorMenu.Options.XKB; desktop_lockscreen_menu = new IndicatorMenu (get_action_group (), options); ((!) desktop_lockscreen_menu).set_sources (get_sources ()); @@ -965,7 +1095,7 @@ public class Indicator.Keyboard.Service : Object { string? variant = null; var sources = get_sources (); - var current = source_settings.get_uint ("current"); + var current = get_current (); if (current < sources.length) { layout = sources[current].layout; @@ -1038,11 +1168,11 @@ public class Indicator.Keyboard.Service : Object { var sources = get_sources (); if (sources.length > 0) { - var current = source_settings.get_uint ("current"); + var current = get_current (); - if (current < sources.length && sources[current].is_ibus) { + if (current < sources.length && !sources[current].is_xkb) { for (var i = 0; i < sources.length; i++) { - if (!sources[i].is_ibus) { + if (sources[i].is_xkb) { get_active_action ().change_state (new Variant.uint32 (i)); break; } @@ -1051,7 +1181,7 @@ public class Indicator.Keyboard.Service : Object { } }); ((!) unity_session).unlocked.connect (() => { - get_active_action ().change_state (source_settings.get_value ("current")); + get_active_action ().change_state (new Variant.uint32 (get_current ())); }); } catch (IOError error) { warning ("error: %s", error.message); |