diff options
author | yusukes@google.com <yusukes@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-12-02 05:21:00 +0000 |
---|---|---|
committer | yusukes@google.com <yusukes@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-12-02 05:21:00 +0000 |
commit | e7bbbb61858e2029ecd216c5ea587e17f2ae9f9e (patch) | |
tree | fa408dd8d019278de83fbdef2ea64afd6811e7de | |
parent | 6da840ffba5ed810fadc8b1fe3edf65a2c65392b (diff) | |
download | chromium_src-e7bbbb61858e2029ecd216c5ea587e17f2ae9f9e.zip chromium_src-e7bbbb61858e2029ecd216c5ea587e17f2ae9f9e.tar.gz chromium_src-e7bbbb61858e2029ecd216c5ea587e17f2ae9f9e.tar.bz2 |
Reduce CPU usage for input method switching.
- Move GetNumActiveInputMethods call from input_method_menu_button.cc to input_method_library.cc so that the IBus function is called only once even when multiple Chrome windows are available.
- Improved InputMethodMenu::InputMethodChanged so that only the first input method button would update Preferences.
- Remove ImePropertiesChanged callback. It's obsolete.
BUG=chromium-os:8553
TEST=manually.
Review URL: http://codereview.chromium.org/4162002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@67973 0039d316-1c4b-4281-b951-d872f2087c98
8 files changed, 117 insertions, 46 deletions
diff --git a/chrome/browser/chromeos/cros/input_method_library.cc b/chrome/browser/chromeos/cros/input_method_library.cc index 1e6f15a..9b5316f 100644 --- a/chrome/browser/chromeos/cros/input_method_library.cc +++ b/chrome/browser/chromeos/cros/input_method_library.cc @@ -23,6 +23,7 @@ #include "chrome/common/notification_service.h" namespace { + const char kIBusDaemonPath[] = "/usr/bin/ibus-daemon"; const char kCandidateWindowPath[] = "/opt/google/chrome/candidate_window"; @@ -290,7 +291,11 @@ class InputMethodLibraryImpl : public InputMethodLibrary, } if (active_input_methods_are_changed) { - FOR_EACH_OBSERVER(Observer, observers_, ActiveInputMethodsChanged(this)); + const size_t num_active_input_methods = GetNumActiveInputMethods(); + FOR_EACH_OBSERVER(Observer, observers_, + ActiveInputMethodsChanged(this, + current_input_method_, + num_active_input_methods)); } } @@ -386,13 +391,29 @@ class InputMethodLibraryImpl : public InputMethodLibrary, previous_input_method_ = current_input_method_; current_input_method_ = new_input_method; } - FOR_EACH_OBSERVER(Observer, observers_, InputMethodChanged(this)); + const size_t num_active_input_methods = GetNumActiveInputMethods(); + FOR_EACH_OBSERVER(Observer, observers_, + InputMethodChanged(this, + previous_input_method_, + current_input_method_, + num_active_input_methods)); + + // Ask the first observer to update preferences. We should not ask every + // observer to do so. Otherwise, we'll end up updating preferences many + // times when many observers are attached (ex. many windows are opened), + // which is unnecessary and expensive. + ObserverListBase<Observer>::Iterator it(observers_); + Observer* first_observer = it.GetNext(); + if (first_observer) { + first_observer->PreferenceUpdateNeeded(this, + previous_input_method_, + current_input_method_); + } } void RegisterProperties(const ImePropertyList& prop_list) { // |prop_list| might be empty. This means "clear all properties." current_ime_properties_ = prop_list; - FOR_EACH_OBSERVER(Observer, observers_, ImePropertiesChanged(this)); } void StartInputMethodProcesses() { @@ -404,7 +425,6 @@ class InputMethodLibraryImpl : public InputMethodLibrary, for (size_t i = 0; i < prop_list.size(); ++i) { FindAndUpdateProperty(prop_list[i], ¤t_ime_properties_); } - FOR_EACH_OBSERVER(Observer, observers_, ImePropertiesChanged(this)); } // Launches an input method procsess specified by the given command diff --git a/chrome/browser/chromeos/cros/input_method_library.h b/chrome/browser/chromeos/cros/input_method_library.h index f3bbe3c..7f55eea 100644 --- a/chrome/browser/chromeos/cros/input_method_library.h +++ b/chrome/browser/chromeos/cros/input_method_library.h @@ -26,14 +26,23 @@ class InputMethodLibrary { public: virtual ~Observer() = 0; // Called when the current input method is changed. - virtual void InputMethodChanged(InputMethodLibrary* obj) = 0; - - // Called when input method properties (see chromeos_input_method.h - // for details) are changed. - virtual void ImePropertiesChanged(InputMethodLibrary* obj) = 0; + virtual void InputMethodChanged( + InputMethodLibrary* obj, + const InputMethodDescriptor& previous_input_method, + const InputMethodDescriptor& current_input_method, + size_t num_active_input_methods) = 0; // Called when the active input methods are changed. - virtual void ActiveInputMethodsChanged(InputMethodLibrary* obj) = 0; + virtual void ActiveInputMethodsChanged( + InputMethodLibrary* obj, + const InputMethodDescriptor& current_input_method, + size_t num_active_input_methods) = 0; + + // Called when the preferences have to be updated. + virtual void PreferenceUpdateNeeded( + InputMethodLibrary* obj, + const InputMethodDescriptor& previous_input_method, + const InputMethodDescriptor& current_input_method) = 0; }; virtual ~InputMethodLibrary() {} diff --git a/chrome/browser/chromeos/login/keyboard_switch_menu.cc b/chrome/browser/chromeos/login/keyboard_switch_menu.cc index de2026b..ff11bee 100644 --- a/chrome/browser/chromeos/login/keyboard_switch_menu.cc +++ b/chrome/browser/chromeos/login/keyboard_switch_menu.cc @@ -24,8 +24,10 @@ KeyboardSwitchMenu::KeyboardSwitchMenu() //////////////////////////////////////////////////////////////////////////////// // InputMethodMenu::InputMethodMenuHost implementation. -void KeyboardSwitchMenu::UpdateUI( - const std::wstring& name, const std::wstring& tooltip) { +void KeyboardSwitchMenu::UpdateUI(const std::string& input_method_id, + const std::wstring& name, + const std::wstring& tooltip, + size_t num_active_input_methods) { // Update all view hierarchies so that the new input method name is shown in // the menu button. views::Widget::NotifyLocaleChanged(); diff --git a/chrome/browser/chromeos/login/keyboard_switch_menu.h b/chrome/browser/chromeos/login/keyboard_switch_menu.h index 64bd2aa..48c0982 100644 --- a/chrome/browser/chromeos/login/keyboard_switch_menu.h +++ b/chrome/browser/chromeos/login/keyboard_switch_menu.h @@ -23,8 +23,10 @@ class KeyboardSwitchMenu : public InputMethodMenu { virtual ~KeyboardSwitchMenu() {} // InputMethodMenu::InputMethodMenuHost implementation. - virtual void UpdateUI( - const std::wstring& name, const std::wstring& tooltip); + virtual void UpdateUI(const std::string& input_method_id, + const std::wstring& name, + const std::wstring& tooltip, + size_t num_active_input_methods); virtual bool ShouldSupportConfigUI() { return false; } virtual void OpenConfigUI() {} diff --git a/chrome/browser/chromeos/status/input_method_menu.cc b/chrome/browser/chromeos/status/input_method_menu.cc index 027f141..8260e087 100644 --- a/chrome/browser/chromeos/status/input_method_menu.cc +++ b/chrome/browser/chromeos/status/input_method_menu.cc @@ -378,16 +378,20 @@ void InputMethodMenu::RunMenu( //////////////////////////////////////////////////////////////////////////////// // InputMethodLibrary::Observer implementation: -void InputMethodMenu::InputMethodChanged(InputMethodLibrary* obj) { +void InputMethodMenu::InputMethodChanged( + InputMethodLibrary* obj, + const InputMethodDescriptor& previous_input_method, + const InputMethodDescriptor& current_input_method, + size_t num_active_input_methods) { UserMetrics::RecordAction( UserMetricsAction("LanguageMenuButton_InputMethodChanged")); + UpdateUIFromInputMethod(current_input_method, num_active_input_methods); +} - const InputMethodDescriptor& previous_input_method = - obj->previous_input_method(); - const InputMethodDescriptor& current_input_method = - obj->current_input_method(); - UpdateUIFromInputMethod(current_input_method); - // Update Chrome prefs as well. +void InputMethodMenu::PreferenceUpdateNeeded( + InputMethodLibrary* obj, + const InputMethodDescriptor& previous_input_method, + const InputMethodDescriptor& current_input_method) { if (is_browser_mode_) { if (pref_service_) { // make sure we're not in unit tests. // Sometimes (e.g. initial boot) |previous_input_method.id| is empty. @@ -418,20 +422,21 @@ void InputMethodMenu::PrepareForMenuOpen() { } } -void InputMethodMenu::ActiveInputMethodsChanged(InputMethodLibrary* obj) { +void InputMethodMenu::ActiveInputMethodsChanged( + InputMethodLibrary* obj, + const InputMethodDescriptor& current_input_method, + size_t num_active_input_methods) { // Update the icon if active input methods are changed. See also - // comments in UpdateUI() - UpdateUIFromInputMethod(obj->current_input_method()); -} - -void InputMethodMenu::ImePropertiesChanged(InputMethodLibrary* obj) { + // comments in UpdateUI() in input_method_menu_button.cc. + UpdateUIFromInputMethod(current_input_method, num_active_input_methods); } void InputMethodMenu::UpdateUIFromInputMethod( - const InputMethodDescriptor& input_method) { + const InputMethodDescriptor& input_method, + size_t num_active_input_methods) { const std::wstring name = GetTextForIndicator(input_method); const std::wstring tooltip = GetTextForMenu(input_method); - UpdateUI(name, tooltip); + UpdateUI(input_method.id, name, tooltip, num_active_input_methods); } void InputMethodMenu::RebuildModel() { diff --git a/chrome/browser/chromeos/status/input_method_menu.h b/chrome/browser/chromeos/status/input_method_menu.h index a132c87..a25ee36 100644 --- a/chrome/browser/chromeos/status/input_method_menu.h +++ b/chrome/browser/chromeos/status/input_method_menu.h @@ -63,9 +63,19 @@ class InputMethodMenu : public views::ViewMenuDelegate, const gfx::Point& pt); // InputMethodLibrary::Observer implementation. - virtual void InputMethodChanged(InputMethodLibrary* obj); - virtual void ImePropertiesChanged(InputMethodLibrary* obj); - virtual void ActiveInputMethodsChanged(InputMethodLibrary* obj); + virtual void InputMethodChanged( + InputMethodLibrary* obj, + const InputMethodDescriptor& previous_input_method, + const InputMethodDescriptor& current_input_method, + size_t num_active_input_methods); + virtual void ActiveInputMethodsChanged( + InputMethodLibrary* obj, + const InputMethodDescriptor& current_input_method, + size_t num_active_input_methods); + virtual void PreferenceUpdateNeeded( + InputMethodLibrary* obj, + const InputMethodDescriptor& previous_input_method, + const InputMethodDescriptor& current_input_method); // NotificationObserver implementation. virtual void Observe(NotificationType type, @@ -89,7 +99,8 @@ class InputMethodMenu : public views::ViewMenuDelegate, protected: // Parses |input_method| and then calls UpdateUI(). - void UpdateUIFromInputMethod(const InputMethodDescriptor& input_method); + void UpdateUIFromInputMethod(const InputMethodDescriptor& input_method, + size_t num_active_input_methods); // Rebuilds model and menu2 objects in preparetion to open the menu. void PrepareForMenuOpen(); @@ -102,8 +113,10 @@ class InputMethodMenu : public views::ViewMenuDelegate, private: // Updates UI of a container of the menu (e.g. the "US" menu button in the // status area). Sub classes have to implement the interface for their own UI. - virtual void UpdateUI( - const std::wstring& name, const std::wstring& tooltip) = 0; + virtual void UpdateUI(const std::string& input_method_id, // e.g. "mozc" + const std::wstring& name, // e.g. "US", "INTL" + const std::wstring& tooltip, + size_t num_active_input_methods) = 0; // Sub classes have to implement the interface. This interface should return // true if the dropdown menu should show an item like "Customize languages diff --git a/chrome/browser/chromeos/status/input_method_menu_button.cc b/chrome/browser/chromeos/status/input_method_menu_button.cc index 1fb5fa2..bc714bc 100644 --- a/chrome/browser/chromeos/status/input_method_menu_button.cc +++ b/chrome/browser/chromeos/status/input_method_menu_button.cc @@ -7,6 +7,7 @@ #include <string> #include "app/resource_bundle.h" +#include "base/utf_string_conversions.h" #include "chrome/browser/chromeos/cros/cros_library.h" #include "chrome/browser/chromeos/cros/keyboard_library.h" #include "chrome/browser/chromeos/input_method/input_method_util.h" @@ -54,11 +55,16 @@ InputMethodMenuButton::InputMethodMenuButton(StatusAreaHost* host) SetShowMultipleIconStates(false); set_alignment(TextButton::ALIGN_CENTER); + chromeos::KeyboardLibrary* keyboard_library = + chromeos::CrosLibrary::Get()->GetKeyboardLibrary(); + const std::string hardware_keyboard_id = // e.g. "xkb:us::eng" + keyboard_library->GetHardwareKeyboardLayoutName(); + // Draw the default indicator "US". The default indicator "US" is used when // |pref_service| is not available (for example, unit tests) or |pref_service| // is available, but Chrome preferences are not available (for example, // initial OS boot). - InputMethodMenuButton::UpdateUI(L"US", L""); + InputMethodMenuButton::UpdateUI(hardware_keyboard_id, L"US", L"", 1); } //////////////////////////////////////////////////////////////////////////////// @@ -74,9 +80,21 @@ gfx::Size InputMethodMenuButton::GetPreferredSize() { void InputMethodMenuButton::OnLocaleChanged() { input_method::OnLocaleChanged(); + + chromeos::InputMethodLibrary* input_method_library = + chromeos::CrosLibrary::Get()->GetInputMethodLibrary(); const InputMethodDescriptor& input_method = - CrosLibrary::Get()->GetInputMethodLibrary()->current_input_method(); - UpdateUIFromInputMethod(input_method); + input_method_library->current_input_method(); + + // In general, we should not call an input method API in the input method + // button classes (status/input_menu_button*.cc) for performance reasons (see + // http://crosbug.com/8284). However, since OnLocaleChanged is called only in + // OOBE/Login screen which does not have two or more Chrome windows, it's okay + // to call GetNumActiveInputMethods here. + const size_t num_active_input_methods = + input_method_library->GetNumActiveInputMethods(); + + UpdateUIFromInputMethod(input_method, num_active_input_methods); Layout(); SchedulePaint(); } @@ -84,16 +102,16 @@ void InputMethodMenuButton::OnLocaleChanged() { //////////////////////////////////////////////////////////////////////////////// // InputMethodMenu::InputMethodMenuHost implementation: -void InputMethodMenuButton::UpdateUI( - const std::wstring& name, const std::wstring& tooltip) { +void InputMethodMenuButton::UpdateUI(const std::string& input_method_id, + const std::wstring& name, + const std::wstring& tooltip, + size_t num_active_input_methods) { // Hide the button only if there is only one input method, and the input // method is a XKB keyboard layout. We don't hide the button for other // types of input methods as these might have intra input method modes, // like Hiragana and Katakana modes in Japanese input methods. - scoped_ptr<InputMethodDescriptors> active_input_methods( - CrosLibrary::Get()->GetInputMethodLibrary()->GetActiveInputMethods()); - if (active_input_methods->size() == 1 && - input_method::IsKeyboardLayout(active_input_methods->at(0).id) && + if (num_active_input_methods == 1 && + input_method::IsKeyboardLayout(input_method_id) && host_->IsBrowserMode()) { // As the disabled color is set to invisible, disabling makes the // button disappear. diff --git a/chrome/browser/chromeos/status/input_method_menu_button.h b/chrome/browser/chromeos/status/input_method_menu_button.h index d7375d3..3a232eb 100644 --- a/chrome/browser/chromeos/status/input_method_menu_button.h +++ b/chrome/browser/chromeos/status/input_method_menu_button.h @@ -29,8 +29,10 @@ class InputMethodMenuButton : public StatusAreaButton, private: // InputMethodMenu implementation. - virtual void UpdateUI( - const std::wstring& name, const std::wstring& tooltip); + virtual void UpdateUI(const std::string& input_method_id, + const std::wstring& name, + const std::wstring& tooltip, + size_t num_active_input_methods); virtual bool ShouldSupportConfigUI(); virtual void OpenConfigUI(); |