From 809760cd3b6c0b24a62336800367f81eb26fecdf Mon Sep 17 00:00:00 2001 From: William Hua Date: Thu, 27 Mar 2014 10:56:42 +1300 Subject: Export separate menus for desktop and greeter. --- lib/Makefile.am | 11 +++-- lib/ibus-menu.vala | 45 +++++++++-------- lib/indicator-menu.vala | 126 ++++++++++++++++++++++++++++++++++++++++++++++++ lib/main.vala | 108 ++++++++++------------------------------- 4 files changed, 179 insertions(+), 111 deletions(-) create mode 100644 lib/indicator-menu.vala (limited to 'lib') diff --git a/lib/Makefile.am b/lib/Makefile.am index 7432d15c..89d8464f 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -6,11 +6,12 @@ AM_VALAFLAGS = --enable-experimental-non-null \ --metadatadir $(top_srcdir)/deps \ --vapidir $(top_srcdir)/deps -indicator_keyboard_service_SOURCES = main.vala \ - source.vala \ - common.vala \ - ibus-menu.vala \ - window-stack.vala \ +indicator_keyboard_service_SOURCES = main.vala \ + source.vala \ + common.vala \ + ibus-menu.vala \ + indicator-menu.vala \ + window-stack.vala \ unity-greeter.vala indicator_keyboard_service_VALAFLAGS = $(AM_VALAFLAGS) \ --pkg gee-1.0 \ diff --git a/lib/ibus-menu.vala b/lib/ibus-menu.vala index 90e87258..c0862ac3 100644 --- a/lib/ibus-menu.vala +++ b/lib/ibus-menu.vala @@ -23,16 +23,16 @@ public class Indicator.Keyboard.IBusMenu : MenuModel { private IBus.PropList? properties; private Menu menu; - private SimpleActionGroup? action_group; + private ActionMap? action_map; private string? radio_name; private SimpleAction? radio_action; private Gee.HashMap radio_properties; - // A list of the action names this menu registers + /* A list of the action names this menu registers. */ private Gee.LinkedList names; - public IBusMenu (SimpleActionGroup? action_group = null, IBus.PropList? properties = null) { + public IBusMenu (ActionMap? action_map = null, IBus.PropList? properties = null) { menu = new Menu (); menu.items_changed.connect ((position, removed, added) => { @@ -40,7 +40,7 @@ public class Indicator.Keyboard.IBusMenu : MenuModel { }); names = new Gee.LinkedList (); - set_action_group (action_group); + set_action_map (action_map); set_properties (properties); } @@ -72,12 +72,12 @@ public class Indicator.Keyboard.IBusMenu : MenuModel { name = @"ibus-$key"; } - // Find an unused action name using a counter - if (action_group != null && (Action?) ((!) action_group).lookup_action (name) != null) { + /* Find an unused action name using a counter. */ + if (action_map != null && (Action?) ((!) action_map).lookup_action (name) != null) { var i = 0; var unique_name = @"$name-$i"; - while ((Action?) ((!) action_group).lookup_action (unique_name) != null) { + while ((Action?) ((!) action_map).lookup_action (unique_name) != null) { i++; unique_name = @"$name-$i"; } @@ -107,10 +107,10 @@ public class Indicator.Keyboard.IBusMenu : MenuModel { if ((string?) property.key != null) { var name = get_action_name (property.key); - if (action_group != null) { + if (action_map != null) { var action = new SimpleAction (name, null); action.activate.connect ((parameter) => { activate (property, property.state); }); - ((!) action_group).add_action (action); + ((!) action_map).add_action (action); names.add (name); } @@ -124,7 +124,7 @@ public class Indicator.Keyboard.IBusMenu : MenuModel { if ((string?) property.key != null) { var name = get_action_name (property.key); - if (action_group != null) { + if (action_map != null) { var state = new Variant.boolean (property.state == IBus.PropState.CHECKED); var action = new SimpleAction.stateful (name, null, state); @@ -139,7 +139,7 @@ public class Indicator.Keyboard.IBusMenu : MenuModel { } }); - ((!) action_group).add_action (action); + ((!) action_map).add_action (action); names.add (name); } @@ -151,8 +151,8 @@ public class Indicator.Keyboard.IBusMenu : MenuModel { private void append_radio_property (IBus.Property property) { if (property.prop_type == IBus.PropType.RADIO) { if ((string?) property.key != null) { - // Create a single action for all radio properties. - if (action_group != null && radio_name == null) { + /* Create a single action for all radio properties. */ + if (action_map != null && radio_name == null) { radio_counter++; radio_name = @"-private-radio-$radio_counter"; radio_action = new SimpleAction.stateful ((!) radio_name, VariantType.STRING, new Variant.string ("")); @@ -172,7 +172,7 @@ public class Indicator.Keyboard.IBusMenu : MenuModel { } }); - ((!) action_group).add_action ((!) radio_action); + ((!) action_map).add_action ((!) radio_action); names.add ((!) radio_name); } @@ -195,7 +195,7 @@ public class Indicator.Keyboard.IBusMenu : MenuModel { private void append_menu_property (IBus.Property property) { if (property.prop_type == IBus.PropType.MENU) { - var submenu = new IBusMenu (action_group, ((!) property).sub_props); + var submenu = new IBusMenu (action_map, ((!) property).sub_props); submenu.activate.connect ((property, state) => { activate (property, state); }); menu.append_submenu (get_label (property), submenu); } @@ -227,8 +227,7 @@ public class Indicator.Keyboard.IBusMenu : MenuModel { } private void update_menu () { - // There's a reference cycle between the action group and the submenus. - // We need to break it here so that those submenus aren't hanging around. + /* Break reference cycle between action map and submenus. */ for (var i = 0; i < menu.get_n_items (); i++) { var submenu = menu.get_item_link (i, Menu.LINK_SUBMENU) as IBusMenu; @@ -250,19 +249,19 @@ public class Indicator.Keyboard.IBusMenu : MenuModel { radio_action = null; radio_name = null; - if (action_group != null) { + if (action_map != null) { foreach (var name in names) { - ((!) action_group).remove_action (name); + ((!) action_map).remove_action (name); } } names.clear (); } - public void set_action_group (SimpleActionGroup? action_group) { - if (action_group != this.action_group) { + public void set_action_map (ActionMap? action_map) { + if (action_map != this.action_map) { remove_actions (); - this.action_group = action_group; + this.action_map = action_map; update_menu (); } } @@ -282,7 +281,7 @@ public class Indicator.Keyboard.IBusMenu : MenuModel { update_menu (); } - // Forward all menu model calls to our internal menu + /* Forward all menu model calls to our internal menu. */ public override Variant get_item_attribute_value (int item_index, string attribute, VariantType? expected_type) { return menu.get_item_attribute_value (item_index, attribute, expected_type); diff --git a/lib/indicator-menu.vala b/lib/indicator-menu.vala new file mode 100644 index 00000000..ab55e808 --- /dev/null +++ b/lib/indicator-menu.vala @@ -0,0 +1,126 @@ +/* + * Copyright 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 as published by + * the Free Software Foundation, version 3 of the License. + * + * 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 . + * + * Authors: William Hua + */ + +public class Indicator.Keyboard.IndicatorMenu : MenuModel { + + public enum Options { + NONE = 0x0, + IBUS = 0x1, + SETTINGS = 0x2 + } + + private Options options; + + private Menu indicator_menu; + private Menu sources_section; + private IBusMenu properties_section; + + public IndicatorMenu (ActionMap? action_map = null, Options options = Options.IBUS | Options.SETTINGS) { + var submenu = new Menu (); + + sources_section = new Menu (); + submenu.append_section (null, sources_section); + + if ((options & Options.IBUS) != Options.NONE) { + properties_section = new IBusMenu (action_map); + properties_section.activate.connect ((property, state) => { activate (property, state); }); + submenu.append_section (null, properties_section); + } + + if ((options & Options.SETTINGS) != Options.NONE) { + var settings_section = new Menu (); + settings_section.append (_ ("Character Map"), "indicator.map"); + settings_section.append (_ ("Keyboard Layout Chart"), "indicator.chart"); + settings_section.append (_ ("Text Entry Settings..."), "indicator.settings"); + submenu.append_section (null, settings_section); + } + + var indicator = new MenuItem.submenu (null, submenu); + indicator.set_attribute ("x-canonical-type", "s", "com.canonical.indicator.root"); + indicator.set_attribute ("x-canonical-secondary-action", "s", "indicator.next"); + indicator.set_attribute ("x-canonical-scroll-action", "s", "indicator.scroll"); + indicator.set_detailed_action ("indicator.indicator"); + + indicator_menu = new Menu (); + indicator_menu.append_item (indicator); + + this.options = options; + } + + public signal void activate (IBus.Property property, IBus.PropState state); + + public void set_sources (Source[] sources) { + sources_section.remove_all (); + + for (var i = 0; i < sources.length; i++) { + var item = new MenuItem (sources[i].name, "indicator.current"); + + item.set_attribute (Menu.ATTRIBUTE_TARGET, "u", i); + + if (sources[i].icon != null) { + item.set_icon ((!) sources[i].icon); + } + + sources_section.append_item (item); + } + } + + public void set_properties (IBus.PropList properties) { + if ((options & Options.IBUS) != Options.NONE) { + properties_section.set_properties (properties); + } + } + + public void update_property (IBus.Property property) { + if ((options & Options.IBUS) != Options.NONE) { + properties_section.update_property (property); + } + } + + public override bool is_mutable () { + return indicator_menu.is_mutable (); + } + + public override int get_n_items () { + return indicator_menu.get_n_items (); + } + + public override void get_item_attributes (int item_index, out HashTable? attributes) { + indicator_menu.get_item_attributes (item_index, out attributes); + } + + public override void get_item_links (int item_index, out HashTable? links) { + indicator_menu.get_item_links (item_index, out links); + } + + public override Variant get_item_attribute_value (int item_index, string attribute, VariantType? expected_type) { + return indicator_menu.get_item_attribute_value (item_index, attribute, expected_type); + } + + public override MenuModel get_item_link (int item_index, string link) { + return indicator_menu.get_item_link (item_index, link); + } + + public override MenuAttributeIter iterate_item_attributes (int item_index) { + return indicator_menu.iterate_item_attributes (item_index); + } + + public override MenuLinkIter iterate_item_links (int item_index) { + return indicator_menu.iterate_item_links (item_index); + } +} diff --git a/lib/main.vala b/lib/main.vala index f012ecb0..473c52d1 100644 --- a/lib/main.vala +++ b/lib/main.vala @@ -44,9 +44,8 @@ public class Indicator.Keyboard.Service : Object { private SimpleActionGroup? action_group; private SimpleAction? indicator_action; - private MenuModel? menu_model; - private Menu? sources_menu; - private IBusMenu? ibus_menu; + private IndicatorMenu? desktop_menu; + private IndicatorMenu? desktop_greeter_menu; private UnityGreeter? unity_greeter; private string? greeter_user; @@ -70,8 +69,12 @@ public class Indicator.Keyboard.Service : Object { } } - if (sources_menu != null) { - update_sources_menu (); + if (desktop_menu != null) { + get_desktop_menu ().set_sources (get_sources ()); + } + + if (desktop_greeter_menu != null) { + get_desktop_greeter_menu ().set_sources (get_sources ()); } if (indicator_action != null) { @@ -597,7 +600,7 @@ public class Indicator.Keyboard.Service : Object { } panel_timeout = Timeout.add (PROPERTIES_DELAY, () => { - update_ibus_menu (list); + get_desktop_menu ().set_properties (list); panel_timeout = 0; return false; }); @@ -605,7 +608,7 @@ public class Indicator.Keyboard.Service : Object { [DBus (visible = false)] private void handle_updated_property (IBus.Property property) { - get_ibus_menu ().update_property (property); + get_desktop_menu ().update_property (property); } [DBus (visible = false)] @@ -705,91 +708,28 @@ public class Indicator.Keyboard.Service : Object { } [DBus (visible = false)] - private void update_sources_menu () { - if (sources_menu != null) { - var menu = get_sources_menu (); - menu.remove_all (); - - var sources = get_sources (); - for (var i = 0; i < sources.length; i++) { - var item = new MenuItem (sources[i].name, "indicator.current"); - item.set_attribute (Menu.ATTRIBUTE_TARGET, "u", i); - - var icon = sources[i].icon; - if (icon != null) { - item.set_icon ((!) icon); - } - - menu.append_item (item); - } - } else { - get_sources_menu (); - } - } - - [DBus (visible = false)] - private Menu get_sources_menu () { - if (sources_menu == null) { - sources_menu = new Menu (); - update_sources_menu (); - } - - return (!) sources_menu; - } - - [DBus (visible = false)] - private void update_ibus_menu (IBus.PropList list) { - get_ibus_menu ().set_properties (list); - } - - [DBus (visible = false)] - private IBusMenu get_ibus_menu () { - if (ibus_menu == null) { - ibus_menu = new IBusMenu (get_action_group ()); - ((!) ibus_menu).activate.connect ((property, state) => { + public IndicatorMenu get_desktop_menu () { + if (desktop_menu == null) { + desktop_menu = new IndicatorMenu (get_action_group ()); + ((!) desktop_menu).set_sources (get_sources ()); + ((!) desktop_menu).activate.connect ((property, state) => { if (panel_service != null) { ((!) panel_service).property_activate (property.key, state); } }); } - return (!) ibus_menu; - } - - [DBus (visible = false)] - protected virtual MenuModel create_menu_model (MenuModel sources_menu, MenuModel ibus_menu) { - var menu = new Menu (); - - var submenu = new Menu (); - - submenu.append_section (null, sources_menu); - submenu.append_section (null, ibus_menu); - - if (!is_login_user ()) { - var section = new Menu (); - section.append (_ ("Character Map"), "indicator.map"); - section.append (_ ("Keyboard Layout Chart"), "indicator.chart"); - section.append (_ ("Text Entry Settings..."), "indicator.settings"); - submenu.append_section (null, section); - } - - var indicator = new MenuItem.submenu ("x", submenu); - indicator.set_attribute ("x-canonical-type", "s", "com.canonical.indicator.root"); - indicator.set_attribute ("x-canonical-secondary-action", "s", "indicator.next"); - indicator.set_attribute ("x-canonical-scroll-action", "s", "indicator.scroll"); - indicator.set_detailed_action ("indicator.indicator"); - menu.append_item (indicator); - - return menu; + return (!) desktop_menu; } [DBus (visible = false)] - public MenuModel get_menu_model () { - if (menu_model == null) { - menu_model = create_menu_model (get_sources_menu (), get_ibus_menu ()); + public IndicatorMenu get_desktop_greeter_menu () { + if (desktop_greeter_menu == null) { + desktop_greeter_menu = new IndicatorMenu (get_action_group (), IndicatorMenu.Options.NONE); + ((!) desktop_greeter_menu).set_sources (get_sources ()); } - return (!) menu_model; + return (!) desktop_greeter_menu; } [DBus (visible = false)] @@ -807,7 +747,8 @@ public class Indicator.Keyboard.Service : Object { private void handle_changed_sources (string key) { sources = null; - update_sources_menu (); + get_desktop_menu ().set_sources (get_sources ()); + get_desktop_greeter_menu ().set_sources (get_sources ()); update_indicator_action (); update_login_layout (); } @@ -897,7 +838,8 @@ public class Indicator.Keyboard.Service : Object { private void handle_bus_acquired (DBusConnection connection, string name) { try { connection.export_action_group ("/com/canonical/indicator/keyboard", get_action_group ()); - connection.export_menu_model ("/com/canonical/indicator/keyboard/desktop", get_menu_model ()); + connection.export_menu_model ("/com/canonical/indicator/keyboard/desktop", get_desktop_menu ()); + connection.export_menu_model ("/com/canonical/indicator/keyboard/desktop_greeter", get_desktop_greeter_menu ()); } catch (Error error) { warning ("error: %s", error.message); } -- cgit v1.2.3