| Index: chrome/browser/chromeos/input_method/input_method_manager_impl.cc
|
| diff --git a/chrome/browser/chromeos/input_method/input_method_manager_impl.cc b/chrome/browser/chromeos/input_method/input_method_manager_impl.cc
|
| index 87518b91185ff9ec288c436f90c1cc5e35fec7f8..6679b587b585e7ee94a2b4cd2f762fc3db7d809d 100644
|
| --- a/chrome/browser/chromeos/input_method/input_method_manager_impl.cc
|
| +++ b/chrome/browser/chromeos/input_method/input_method_manager_impl.cc
|
| @@ -6,6 +6,8 @@
|
|
|
| #include <algorithm> // std::find
|
|
|
| +#include <sstream>
|
| +
|
| #include "ash/ime/input_method_menu_item.h"
|
| #include "ash/ime/input_method_menu_manager.h"
|
| #include "base/basictypes.h"
|
| @@ -22,6 +24,8 @@
|
| #include "chrome/browser/chromeos/input_method/component_extension_ime_manager_impl.h"
|
| #include "chrome/browser/chromeos/input_method/input_method_engine.h"
|
| #include "chrome/browser/chromeos/language_preferences.h"
|
| +#include "chrome/browser/chromeos/login/session/user_session_manager.h"
|
| +#include "chrome/browser/chromeos/profiles/profile_helper.h"
|
| #include "chrome/browser/profiles/profile_manager.h"
|
| #include "chrome/common/pref_names.h"
|
| #include "chromeos/ime/component_extension_ime_manager.h"
|
| @@ -29,6 +33,7 @@
|
| #include "chromeos/ime/fake_ime_keyboard.h"
|
| #include "chromeos/ime/ime_keyboard.h"
|
| #include "chromeos/ime/input_method_delegate.h"
|
| +#include "components/user_manager/user_manager.h"
|
| #include "third_party/icu/source/common/unicode/uloc.h"
|
| #include "ui/base/accelerators/accelerator.h"
|
|
|
| @@ -45,113 +50,96 @@ bool Contains(const std::vector<std::string>& container,
|
|
|
| } // namespace
|
|
|
| -bool InputMethodManagerImpl::IsLoginKeyboard(
|
| - const std::string& layout) const {
|
| - return util_.IsLoginKeyboard(layout);
|
| -}
|
| +// ------------------------ InputMethodManagerImpl::StateImpl
|
|
|
| -bool InputMethodManagerImpl::MigrateInputMethods(
|
| - std::vector<std::string>* input_method_ids) {
|
| - return util_.MigrateInputMethods(input_method_ids);
|
| +InputMethodManagerImpl::StateImpl::StateImpl(InputMethodManagerImpl* manager,
|
| + Profile* profile)
|
| + : profile(profile), manager_(manager) {
|
| }
|
|
|
| -InputMethodManagerImpl::InputMethodManagerImpl(
|
| - scoped_ptr<InputMethodDelegate> delegate, bool enable_extension_loading)
|
| - : delegate_(delegate.Pass()),
|
| - state_(STATE_LOGIN_SCREEN),
|
| - util_(delegate_.get()),
|
| - component_extension_ime_manager_(new ComponentExtensionIMEManager()),
|
| - enable_extension_loading_(enable_extension_loading) {
|
| - if (base::SysInfo::IsRunningOnChromeOS())
|
| - keyboard_.reset(ImeKeyboard::Create());
|
| - else
|
| - keyboard_.reset(new FakeImeKeyboard());
|
| -
|
| - // Initializes the system IME list.
|
| - scoped_ptr<ComponentExtensionIMEManagerDelegate> comp_delegate(
|
| - new ComponentExtensionIMEManagerImpl());
|
| - component_extension_ime_manager_->Initialize(comp_delegate.Pass());
|
| - util_.ResetInputMethods(
|
| - component_extension_ime_manager_->GetAllIMEAsInputMethodDescriptor());
|
| +InputMethodManagerImpl::StateImpl::~StateImpl() {
|
| }
|
|
|
| -InputMethodManagerImpl::~InputMethodManagerImpl() {
|
| - if (candidate_window_controller_.get())
|
| - candidate_window_controller_->RemoveObserver(this);
|
| -}
|
| +void InputMethodManagerImpl::StateImpl::InitFrom(const StateImpl& other) {
|
| + previous_input_method = other.previous_input_method;
|
| + current_input_method = other.current_input_method;
|
|
|
| -void InputMethodManagerImpl::AddObserver(
|
| - InputMethodManager::Observer* observer) {
|
| - observers_.AddObserver(observer);
|
| -}
|
| + active_input_method_ids = other.active_input_method_ids;
|
|
|
| -void InputMethodManagerImpl::AddCandidateWindowObserver(
|
| - InputMethodManager::CandidateWindowObserver* observer) {
|
| - candidate_window_observers_.AddObserver(observer);
|
| -}
|
| + pending_input_method_id = other.pending_input_method_id;
|
|
|
| -void InputMethodManagerImpl::RemoveObserver(
|
| - InputMethodManager::Observer* observer) {
|
| - observers_.RemoveObserver(observer);
|
| + enabled_extension_imes = other.enabled_extension_imes;
|
| + extra_input_methods = other.extra_input_methods;
|
| }
|
|
|
| -void InputMethodManagerImpl::RemoveCandidateWindowObserver(
|
| - InputMethodManager::CandidateWindowObserver* observer) {
|
| - candidate_window_observers_.RemoveObserver(observer);
|
| +bool InputMethodManagerImpl::StateImpl::IsActive() const {
|
| + return manager_->state_.get() == this;
|
| }
|
|
|
| -InputMethodManager::State InputMethodManagerImpl::GetState() {
|
| - return state_;
|
| -}
|
| -
|
| -void InputMethodManagerImpl::SetState(State new_state) {
|
| - const State old_state = state_;
|
| - state_ = new_state;
|
| - switch (state_) {
|
| - case STATE_LOGIN_SCREEN:
|
| - break;
|
| - case STATE_BROWSER_SCREEN:
|
| - if (old_state == STATE_LOCK_SCREEN)
|
| - OnScreenUnlocked();
|
| - break;
|
| - case STATE_LOCK_SCREEN:
|
| - OnScreenLocked();
|
| - break;
|
| - case STATE_TERMINATING: {
|
| - if (candidate_window_controller_.get())
|
| - candidate_window_controller_.reset();
|
| - break;
|
| - }
|
| +std::string InputMethodManagerImpl::StateImpl::Dump() const {
|
| + std::ostringstream os;
|
| +
|
| + os << "################# "
|
| + << (profile ? profile->GetProfileName() : std::string("NULL"))
|
| + << " #################\n";
|
| +
|
| + os << "previous_input_method: '"
|
| + << previous_input_method.GetPreferredKeyboardLayout() << "'\n";
|
| + os << "current_input_method: '"
|
| + << current_input_method.GetPreferredKeyboardLayout() << "'\n";
|
| + os << "active_input_method_ids (size=" << active_input_method_ids.size()
|
| + << "):";
|
| + for (size_t i = 0; i < active_input_method_ids.size(); ++i) {
|
| + os << " '" << active_input_method_ids[i] << "',";
|
| }
|
| + os << "\n";
|
| + os << "enabled_extension_imes (size=" << enabled_extension_imes.size()
|
| + << "):";
|
| + for (size_t i = 0; i < enabled_extension_imes.size(); ++i) {
|
| + os << " '" << enabled_extension_imes[i] << "'\n";
|
| + }
|
| + os << "\n";
|
| + os << "extra_input_methods (size=" << extra_input_methods.size() << "):";
|
| + for (std::map<std::string, InputMethodDescriptor>::const_iterator it =
|
| + extra_input_methods.begin();
|
| + it != extra_input_methods.end();
|
| + ++it) {
|
| + os << " '" << it->first << "' => '" << it->second.id() << "',\n";
|
| + }
|
| + os << "pending_input_method_id: '" << pending_input_method_id << "'\n";
|
| +
|
| + return os.str();
|
| }
|
|
|
| -scoped_ptr<InputMethodDescriptors>
|
| -InputMethodManagerImpl::GetSupportedInputMethods() const {
|
| - return scoped_ptr<InputMethodDescriptors>(new InputMethodDescriptors).Pass();
|
| +scoped_refptr<InputMethodManager::State>
|
| +InputMethodManagerImpl::StateImpl::Clone() const {
|
| + scoped_refptr<StateImpl> new_state(new StateImpl(this->manager_, profile));
|
| + new_state->InitFrom(*this);
|
| + return scoped_refptr<InputMethodManager::State>(new_state.get());
|
| }
|
|
|
| scoped_ptr<InputMethodDescriptors>
|
| -InputMethodManagerImpl::GetActiveInputMethods() const {
|
| +InputMethodManagerImpl::StateImpl::GetActiveInputMethods() const {
|
| scoped_ptr<InputMethodDescriptors> result(new InputMethodDescriptors);
|
| // Build the active input method descriptors from the active input
|
| - // methods cache |active_input_method_ids_|.
|
| - for (size_t i = 0; i < active_input_method_ids_.size(); ++i) {
|
| - const std::string& input_method_id = active_input_method_ids_[i];
|
| + // methods cache |active_input_method_ids|.
|
| + for (size_t i = 0; i < active_input_method_ids.size(); ++i) {
|
| + const std::string& input_method_id = active_input_method_ids[i];
|
| const InputMethodDescriptor* descriptor =
|
| - util_.GetInputMethodDescriptorFromId(input_method_id);
|
| + manager_->util_.GetInputMethodDescriptorFromId(input_method_id);
|
| if (descriptor) {
|
| result->push_back(*descriptor);
|
| } else {
|
| std::map<std::string, InputMethodDescriptor>::const_iterator ix =
|
| - extra_input_methods_.find(input_method_id);
|
| - if (ix != extra_input_methods_.end())
|
| + extra_input_methods.find(input_method_id);
|
| + if (ix != extra_input_methods.end())
|
| result->push_back(ix->second);
|
| else
|
| DVLOG(1) << "Descriptor is not found for: " << input_method_id;
|
| }
|
| }
|
| if (result->empty()) {
|
| - // Initially |active_input_method_ids_| is empty. browser_tests might take
|
| + // Initially |active_input_method_ids| is empty. browser_tests might take
|
| // this path.
|
| result->push_back(
|
| InputMethodUtil::GetFallbackInputMethodDescriptor());
|
| @@ -160,43 +148,43 @@ InputMethodManagerImpl::GetActiveInputMethods() const {
|
| }
|
|
|
| const std::vector<std::string>&
|
| -InputMethodManagerImpl::GetActiveInputMethodIds() const {
|
| - return active_input_method_ids_;
|
| +InputMethodManagerImpl::StateImpl::GetActiveInputMethodIds() const {
|
| + return active_input_method_ids;
|
| }
|
|
|
| -size_t InputMethodManagerImpl::GetNumActiveInputMethods() const {
|
| - return active_input_method_ids_.size();
|
| +size_t InputMethodManagerImpl::StateImpl::GetNumActiveInputMethods() const {
|
| + return active_input_method_ids.size();
|
| }
|
|
|
| -const InputMethodDescriptor* InputMethodManagerImpl::GetInputMethodFromId(
|
| +const InputMethodDescriptor*
|
| +InputMethodManagerImpl::StateImpl::GetInputMethodFromId(
|
| const std::string& input_method_id) const {
|
| - const InputMethodDescriptor* ime = util_.GetInputMethodDescriptorFromId(
|
| - input_method_id);
|
| + const InputMethodDescriptor* ime =
|
| + manager_->util_.GetInputMethodDescriptorFromId(input_method_id);
|
| if (!ime) {
|
| std::map<std::string, InputMethodDescriptor>::const_iterator ix =
|
| - extra_input_methods_.find(input_method_id);
|
| - if (ix != extra_input_methods_.end())
|
| + extra_input_methods.find(input_method_id);
|
| + if (ix != extra_input_methods.end())
|
| ime = &ix->second;
|
| }
|
| return ime;
|
| }
|
|
|
| -void InputMethodManagerImpl::EnableLoginLayouts(
|
| +void InputMethodManagerImpl::StateImpl::EnableLoginLayouts(
|
| const std::string& language_code,
|
| const std::vector<std::string>& initial_layouts) {
|
| - if (state_ == STATE_TERMINATING)
|
| + if (manager_->ui_session_ == STATE_TERMINATING)
|
| return;
|
|
|
| // First, hardware keyboard layout should be shown.
|
| std::vector<std::string> candidates =
|
| - util_.GetHardwareLoginInputMethodIds();
|
| + manager_->util_.GetHardwareLoginInputMethodIds();
|
|
|
| - // Seocnd, locale based input method should be shown.
|
| + // Second, locale based input method should be shown.
|
| // Add input methods associated with the language.
|
| std::vector<std::string> layouts_from_locale;
|
| - util_.GetInputMethodIdsFromLanguageCode(language_code,
|
| - kKeyboardLayoutsOnly,
|
| - &layouts_from_locale);
|
| + manager_->util_.GetInputMethodIdsFromLanguageCode(
|
| + language_code, kKeyboardLayoutsOnly, &layouts_from_locale);
|
| candidates.insert(candidates.end(), layouts_from_locale.begin(),
|
| layouts_from_locale.end());
|
|
|
| @@ -205,8 +193,8 @@ void InputMethodManagerImpl::EnableLoginLayouts(
|
| // layouts, so it appears first on the list of active input
|
| // methods at the input language status menu.
|
| for (size_t i = 0; i < initial_layouts.size(); ++i) {
|
| - if (util_.IsValidInputMethodId(initial_layouts[i])) {
|
| - if (IsLoginKeyboard(initial_layouts[i])) {
|
| + if (manager_->util_.IsValidInputMethodId(initial_layouts[i])) {
|
| + if (manager_->IsLoginKeyboard(initial_layouts[i])) {
|
| layouts.push_back(initial_layouts[i]);
|
| } else {
|
| DVLOG(1)
|
| @@ -224,30 +212,70 @@ void InputMethodManagerImpl::EnableLoginLayouts(
|
| const std::string& candidate = candidates[i];
|
| // Not efficient, but should be fine, as the two vectors are very
|
| // short (2-5 items).
|
| - if (!Contains(layouts, candidate) && IsLoginKeyboard(candidate))
|
| + if (!Contains(layouts, candidate) && manager_->IsLoginKeyboard(candidate))
|
| layouts.push_back(candidate);
|
| }
|
|
|
| - MigrateInputMethods(&layouts);
|
| - active_input_method_ids_.swap(layouts);
|
| + manager_->MigrateInputMethods(&layouts);
|
| + active_input_method_ids.swap(layouts);
|
| +
|
| + if (IsActive()) {
|
| + // Initialize candidate window controller and widgets such as
|
| + // candidate window, infolist and mode indicator. Note, mode
|
| + // indicator is used by only keyboard layout input methods.
|
| + if (active_input_method_ids.size() > 1)
|
| + manager_->MaybeInitializeCandidateWindowController();
|
| +
|
| + // you can pass empty |initial_layout|.
|
| + ChangeInputMethod(initial_layouts.empty()
|
| + ? std::string()
|
| + : extension_ime_util::GetInputMethodIDByEngineID(
|
| + initial_layouts[0]),
|
| + false);
|
| + }
|
| +}
|
|
|
| - // Initialize candidate window controller and widgets such as
|
| - // candidate window, infolist and mode indicator. Note, mode
|
| - // indicator is used by only keyboard layout input methods.
|
| - if (active_input_method_ids_.size() > 1)
|
| - MaybeInitializeCandidateWindowController();
|
| +void InputMethodManagerImpl::StateImpl::EnableLockScreenLayouts() {
|
| + std::set<std::string> added_ids;
|
|
|
| - // you can pass empty |initial_layout|.
|
| - ChangeInputMethod(initial_layouts.empty() ? "" :
|
| - extension_ime_util::GetInputMethodIDByEngineID(initial_layouts[0]));
|
| + const std::vector<std::string>& hardware_keyboard_ids =
|
| + manager_->util_.GetHardwareLoginInputMethodIds();
|
| +
|
| + std::vector<std::string> new_active_input_method_ids;
|
| + for (size_t i = 0; i < active_input_method_ids.size(); ++i) {
|
| + const std::string& input_method_id = active_input_method_ids[i];
|
| + // Skip if it's not a keyboard layout. Drop input methods including
|
| + // extension ones.
|
| + if (!manager_->IsLoginKeyboard(input_method_id) ||
|
| + added_ids.count(input_method_id)) {
|
| + continue;
|
| + }
|
| + new_active_input_method_ids.push_back(input_method_id);
|
| + added_ids.insert(input_method_id);
|
| + }
|
| +
|
| + // We'll add the hardware keyboard if it's not included in
|
| + // |active_input_method_ids| so that the user can always use the hardware
|
| + // keyboard on the screen locker.
|
| + for (size_t i = 0; i < hardware_keyboard_ids.size(); ++i) {
|
| + if (added_ids.count(hardware_keyboard_ids[i]))
|
| + continue;
|
| + new_active_input_method_ids.push_back(hardware_keyboard_ids[i]);
|
| + added_ids.insert(hardware_keyboard_ids[i]);
|
| + }
|
| +
|
| + active_input_method_ids.swap(new_active_input_method_ids);
|
| +
|
| + // Re-check current_input_method.
|
| + ChangeInputMethod(current_input_method.id(), false);
|
| }
|
|
|
| // Adds new input method to given list.
|
| -bool InputMethodManagerImpl::EnableInputMethodImpl(
|
| +bool InputMethodManagerImpl::StateImpl::EnableInputMethodImpl(
|
| const std::string& input_method_id,
|
| std::vector<std::string>* new_active_input_method_ids) const {
|
| DCHECK(new_active_input_method_ids);
|
| - if (!util_.IsValidInputMethodId(input_method_id)) {
|
| + if (!manager_->util_.IsValidInputMethodId(input_method_id)) {
|
| DVLOG(1) << "EnableInputMethod: Invalid ID: " << input_method_id;
|
| return false;
|
| }
|
| @@ -258,28 +286,18 @@ bool InputMethodManagerImpl::EnableInputMethodImpl(
|
| return true;
|
| }
|
|
|
| -// Starts or stops the system input method framework as needed.
|
| -void InputMethodManagerImpl::ReconfigureIMFramework() {
|
| - LoadNecessaryComponentExtensions();
|
| -
|
| - // Initialize candidate window controller and widgets such as
|
| - // candidate window, infolist and mode indicator. Note, mode
|
| - // indicator is used by only keyboard layout input methods.
|
| - MaybeInitializeCandidateWindowController();
|
| -}
|
| -
|
| -bool InputMethodManagerImpl::EnableInputMethod(
|
| +bool InputMethodManagerImpl::StateImpl::EnableInputMethod(
|
| const std::string& input_method_id) {
|
| - if (!EnableInputMethodImpl(input_method_id, &active_input_method_ids_))
|
| + if (!EnableInputMethodImpl(input_method_id, &active_input_method_ids))
|
| return false;
|
|
|
| - ReconfigureIMFramework();
|
| + manager_->ReconfigureIMFramework(this);
|
| return true;
|
| }
|
|
|
| -bool InputMethodManagerImpl::ReplaceEnabledInputMethods(
|
| +bool InputMethodManagerImpl::StateImpl::ReplaceEnabledInputMethods(
|
| const std::vector<std::string>& new_active_input_method_ids) {
|
| - if (state_ == STATE_TERMINATING)
|
| + if (manager_->ui_session_ == STATE_TERMINATING)
|
| return false;
|
|
|
| // Filter unknown or obsolete IDs.
|
| @@ -296,186 +314,83 @@ bool InputMethodManagerImpl::ReplaceEnabledInputMethods(
|
|
|
| // Copy extension IDs to |new_active_input_method_ids_filtered|. We have to
|
| // keep relative order of the extension input method IDs.
|
| - for (size_t i = 0; i < active_input_method_ids_.size(); ++i) {
|
| - const std::string& input_method_id = active_input_method_ids_[i];
|
| + for (size_t i = 0; i < active_input_method_ids.size(); ++i) {
|
| + const std::string& input_method_id = active_input_method_ids[i];
|
| if (extension_ime_util::IsExtensionIME(input_method_id))
|
| new_active_input_method_ids_filtered.push_back(input_method_id);
|
| }
|
| - active_input_method_ids_.swap(new_active_input_method_ids_filtered);
|
| - MigrateInputMethods(&active_input_method_ids_);
|
| + active_input_method_ids.swap(new_active_input_method_ids_filtered);
|
| + manager_->MigrateInputMethods(&active_input_method_ids);
|
|
|
| - ReconfigureIMFramework();
|
| + manager_->ReconfigureIMFramework(this);
|
|
|
| - // If |current_input_method| is no longer in |active_input_method_ids_|,
|
| - // ChangeInputMethod() picks the first one in |active_input_method_ids_|.
|
| - ChangeInputMethod(current_input_method_.id());
|
| + // If |current_input_method| is no longer in |active_input_method_ids|,
|
| + // ChangeInputMethod() picks the first one in |active_input_method_ids|.
|
| + ChangeInputMethod(current_input_method.id(), false);
|
| return true;
|
| }
|
|
|
| -void InputMethodManagerImpl::ChangeInputMethod(
|
| - const std::string& input_method_id) {
|
| - ChangeInputMethodInternal(input_method_id, false);
|
| -}
|
| -
|
| -bool InputMethodManagerImpl::ChangeInputMethodInternal(
|
| +void InputMethodManagerImpl::StateImpl::ChangeInputMethod(
|
| const std::string& input_method_id,
|
| bool show_message) {
|
| - if (state_ == STATE_TERMINATING)
|
| - return false;
|
| -
|
| - std::string input_method_id_to_switch = input_method_id;
|
| -
|
| - // Sanity check.
|
| - if (!InputMethodIsActivated(input_method_id)) {
|
| - // For 3rd party IME, when the user just logged in, SetEnabledExtensionImes
|
| - // happens after activating the 3rd party IME.
|
| - // So here to record the 3rd party IME to be activated, and activate it
|
| - // when SetEnabledExtensionImes happens later.
|
| - if (extension_ime_util::IsExtensionIME(input_method_id))
|
| - pending_input_method_id_ = input_method_id;
|
| -
|
| - scoped_ptr<InputMethodDescriptors> input_methods(GetActiveInputMethods());
|
| - DCHECK(!input_methods->empty());
|
| - input_method_id_to_switch = input_methods->at(0).id();
|
| - if (!input_method_id.empty()) {
|
| - DVLOG(1) << "Can't change the current input method to "
|
| - << input_method_id << " since the engine is not enabled. "
|
| - << "Switch to " << input_method_id_to_switch << " instead.";
|
| - }
|
| - }
|
| -
|
| - // Hide candidate window and info list.
|
| - if (candidate_window_controller_.get())
|
| - candidate_window_controller_->Hide();
|
| -
|
| - // TODO(komatsu): Check if it is necessary to perform the above routine
|
| - // when the current input method is equal to |input_method_id_to_swich|.
|
| - if (current_input_method_.id() != input_method_id_to_switch) {
|
| - // Clear property list. Property list would be updated by
|
| - // extension IMEs via InputMethodEngine::(Set|Update)MenuItems.
|
| - // If the current input method is a keyboard layout, empty
|
| - // properties are sufficient.
|
| - const ash::ime::InputMethodMenuItemList empty_menu_item_list;
|
| - ash::ime::InputMethodMenuManager* input_method_menu_manager =
|
| - ash::ime::InputMethodMenuManager::GetInstance();
|
| - input_method_menu_manager->SetCurrentInputMethodMenuItemList(
|
| - empty_menu_item_list);
|
| -
|
| - const InputMethodDescriptor* descriptor = NULL;
|
| - if (extension_ime_util::IsExtensionIME(input_method_id_to_switch)) {
|
| - DCHECK(extra_input_methods_.find(input_method_id_to_switch) !=
|
| - extra_input_methods_.end());
|
| - descriptor = &(extra_input_methods_[input_method_id_to_switch]);
|
| - } else {
|
| - descriptor =
|
| - util_.GetInputMethodDescriptorFromId(input_method_id_to_switch);
|
| - if (!descriptor)
|
| - LOG(ERROR) << "Unknown input method id: " << input_method_id_to_switch;
|
| - }
|
| - DCHECK(descriptor);
|
| -
|
| - previous_input_method_ = current_input_method_;
|
| - current_input_method_ = *descriptor;
|
| - }
|
| -
|
| - // Disable the current engine handler.
|
| - IMEEngineHandlerInterface* engine =
|
| - IMEBridge::Get()->GetCurrentEngineHandler();
|
| - if (engine)
|
| - engine->Disable();
|
| -
|
| - // Configure the next engine handler.
|
| - // This must be after |current_input_method_| has been set to new input
|
| - // method, because engine's Enable() method needs to access it.
|
| - const std::string& extension_id =
|
| - extension_ime_util::GetExtensionIDFromInputMethodID(
|
| - input_method_id_to_switch);
|
| - const std::string& component_id =
|
| - extension_ime_util::GetComponentIDByInputMethodID(
|
| - input_method_id_to_switch);
|
| - engine = engine_map_[extension_id];
|
| - IMEBridge::Get()->SetCurrentEngineHandler(engine);
|
| - if (engine)
|
| - engine->Enable(component_id);
|
| + if (manager_->ui_session_ == STATE_TERMINATING)
|
| + return;
|
|
|
| - // Change the keyboard layout to a preferred layout for the input method.
|
| - if (!keyboard_->SetCurrentKeyboardLayoutByName(
|
| - current_input_method_.GetPreferredKeyboardLayout())) {
|
| - LOG(ERROR) << "Failed to change keyboard layout to "
|
| - << current_input_method_.GetPreferredKeyboardLayout();
|
| + bool notify_menu = false;
|
| + // For 3rd party IME, when the user just logged in, SetEnabledExtensionImes
|
| + // happens after activating the 3rd party IME.
|
| + // So here to record the 3rd party IME to be activated, and activate it
|
| + // when SetEnabledExtensionImes happens later.
|
| + if (MethodAwaitsExtensionLoad(input_method_id))
|
| + pending_input_method_id = input_method_id;
|
| +
|
| + // Always lookup input method, even if it is the same as
|
| + // |current_input_method| because If it is no longer in
|
| + // |active_input_method_ids|, pick the first one in
|
| + // |active_input_method_ids|.
|
| + const InputMethodDescriptor* descriptor =
|
| + manager_->LookupInputMethod(input_method_id, this);
|
| + if (descriptor->id() != current_input_method.id()) {
|
| + previous_input_method = current_input_method;
|
| + current_input_method = *descriptor;
|
| + notify_menu = true;
|
| }
|
|
|
| - // Update input method indicators (e.g. "US", "DV") in Chrome windows.
|
| - FOR_EACH_OBSERVER(InputMethodManager::Observer,
|
| - observers_,
|
| - InputMethodChanged(this, show_message));
|
| - return true;
|
| + // Always change input method even if it is the same.
|
| + // TODO(komatsu): Revisit if this is neccessary.
|
| + if (IsActive())
|
| + manager_->ChangeInputMethodInternal(*descriptor, show_message, notify_menu);
|
| }
|
|
|
| -void InputMethodManagerImpl::LoadNecessaryComponentExtensions() {
|
| - // Load component extensions but also update |active_input_method_ids_| as
|
| - // some component extension IMEs may have been removed from the Chrome OS
|
| - // image. If specified component extension IME no longer exists, falling back
|
| - // to an existing IME.
|
| - std::vector<std::string> unfiltered_input_method_ids;
|
| - unfiltered_input_method_ids.swap(active_input_method_ids_);
|
| - for (size_t i = 0; i < unfiltered_input_method_ids.size(); ++i) {
|
| - if (!extension_ime_util::IsComponentExtensionIME(
|
| - unfiltered_input_method_ids[i])) {
|
| - // Legacy IMEs or xkb layouts are alwayes active.
|
| - active_input_method_ids_.push_back(unfiltered_input_method_ids[i]);
|
| - } else if (component_extension_ime_manager_->IsWhitelisted(
|
| - unfiltered_input_method_ids[i])) {
|
| - if (enable_extension_loading_)
|
| - component_extension_ime_manager_->LoadComponentExtensionIME(
|
| - unfiltered_input_method_ids[i]);
|
| - active_input_method_ids_.push_back(unfiltered_input_method_ids[i]);
|
| - }
|
| - }
|
| -}
|
| -
|
| -void InputMethodManagerImpl::ActivateInputMethodMenuItem(
|
| - const std::string& key) {
|
| - DCHECK(!key.empty());
|
| -
|
| - if (ash::ime::InputMethodMenuManager::GetInstance()->
|
| - HasInputMethodMenuItemForKey(key)) {
|
| - IMEEngineHandlerInterface* engine =
|
| - IMEBridge::Get()->GetCurrentEngineHandler();
|
| - if (engine)
|
| - engine->PropertyActivate(key);
|
| - return;
|
| - }
|
| -
|
| - DVLOG(1) << "ActivateInputMethodMenuItem: unknown key: " << key;
|
| +bool InputMethodManagerImpl::StateImpl::MethodAwaitsExtensionLoad(
|
| + const std::string& input_method_id) const {
|
| + // For 3rd party IME, when the user just logged in, SetEnabledExtensionImes
|
| + // happens after activating the 3rd party IME.
|
| + // So here to record the 3rd party IME to be activated, and activate it
|
| + // when SetEnabledExtensionImes happens later.
|
| + return !InputMethodIsActivated(input_method_id) &&
|
| + extension_ime_util::IsExtensionIME(input_method_id);
|
| }
|
|
|
| -void InputMethodManagerImpl::AddInputMethodExtension(
|
| +void InputMethodManagerImpl::StateImpl::AddInputMethodExtension(
|
| const std::string& extension_id,
|
| const InputMethodDescriptors& descriptors,
|
| InputMethodEngineInterface* engine) {
|
| - if (state_ == STATE_TERMINATING)
|
| + if (manager_->ui_session_ == STATE_TERMINATING)
|
| return;
|
|
|
| DCHECK(engine);
|
|
|
| - engine_map_[extension_id] = engine;
|
| -
|
| - if (extension_id == extension_ime_util::GetExtensionIDFromInputMethodID(
|
| - current_input_method_.id())) {
|
| - IMEBridge::Get()->SetCurrentEngineHandler(engine);
|
| - engine->Enable(extension_ime_util::GetComponentIDByInputMethodID(
|
| - current_input_method_.id()));
|
| - }
|
| + manager_->engine_map_[extension_id] = engine;
|
|
|
| bool contain = false;
|
| for (size_t i = 0; i < descriptors.size(); i++) {
|
| const InputMethodDescriptor& descriptor = descriptors[i];
|
| const std::string& id = descriptor.id();
|
| - extra_input_methods_[id] = descriptor;
|
| - if (Contains(enabled_extension_imes_, id)) {
|
| - if (!Contains(active_input_method_ids_, id)) {
|
| - active_input_method_ids_.push_back(id);
|
| + extra_input_methods[id] = descriptor;
|
| + if (Contains(enabled_extension_imes, id)) {
|
| + if (!Contains(active_input_method_ids, id)) {
|
| + active_input_method_ids.push_back(id);
|
| } else {
|
| DVLOG(1) << "AddInputMethodExtension: already added: " << id << ", "
|
| << descriptor.name();
|
| @@ -484,111 +399,121 @@ void InputMethodManagerImpl::AddInputMethodExtension(
|
| }
|
| }
|
|
|
| - // Ensure that the input method daemon is running.
|
| - if (contain)
|
| - MaybeInitializeCandidateWindowController();
|
| + if (IsActive()) {
|
| + if (extension_id == extension_ime_util::GetExtensionIDFromInputMethodID(
|
| + current_input_method.id())) {
|
| + IMEBridge::Get()->SetCurrentEngineHandler(engine);
|
| + engine->Enable(extension_ime_util::GetComponentIDByInputMethodID(
|
| + current_input_method.id()));
|
| + }
|
| +
|
| + // Ensure that the input method daemon is running.
|
| + if (contain)
|
| + manager_->MaybeInitializeCandidateWindowController();
|
| + }
|
| }
|
|
|
| -void InputMethodManagerImpl::RemoveInputMethodExtension(
|
| +void InputMethodManagerImpl::StateImpl::RemoveInputMethodExtension(
|
| const std::string& extension_id) {
|
| // Remove the active input methods with |extension_id|.
|
| std::vector<std::string> new_active_input_method_ids;
|
| - for (size_t i = 0; i < active_input_method_ids_.size(); ++i) {
|
| + for (size_t i = 0; i < active_input_method_ids.size(); ++i) {
|
| if (extension_id != extension_ime_util::GetExtensionIDFromInputMethodID(
|
| - active_input_method_ids_[i]))
|
| - new_active_input_method_ids.push_back(active_input_method_ids_[i]);
|
| + active_input_method_ids[i]))
|
| + new_active_input_method_ids.push_back(active_input_method_ids[i]);
|
| }
|
| - active_input_method_ids_.swap(new_active_input_method_ids);
|
| + active_input_method_ids.swap(new_active_input_method_ids);
|
|
|
| // Remove the extra input methods with |extension_id|.
|
| std::map<std::string, InputMethodDescriptor> new_extra_input_methods;
|
| for (std::map<std::string, InputMethodDescriptor>::iterator i =
|
| - extra_input_methods_.begin();
|
| - i != extra_input_methods_.end();
|
| + extra_input_methods.begin();
|
| + i != extra_input_methods.end();
|
| ++i) {
|
| if (extension_id !=
|
| extension_ime_util::GetExtensionIDFromInputMethodID(i->first))
|
| new_extra_input_methods[i->first] = i->second;
|
| }
|
| - extra_input_methods_.swap(new_extra_input_methods);
|
| -
|
| - if (IMEBridge::Get()->GetCurrentEngineHandler() == engine_map_[extension_id])
|
| - IMEBridge::Get()->SetCurrentEngineHandler(NULL);
|
| - engine_map_.erase(extension_id);
|
| + extra_input_methods.swap(new_extra_input_methods);
|
|
|
| - // No need to switch input method when terminating.
|
| - if (state_ != STATE_TERMINATING) {
|
| - // If |current_input_method| is no longer in |active_input_method_ids_|,
|
| - // switch to the first one in |active_input_method_ids_|.
|
| - ChangeInputMethod(current_input_method_.id());
|
| + if (IsActive()) {
|
| + if (IMEBridge::Get()->GetCurrentEngineHandler() ==
|
| + manager_->engine_map_[extension_id]) {
|
| + IMEBridge::Get()->SetCurrentEngineHandler(NULL);
|
| + }
|
| + manager_->engine_map_.erase(extension_id);
|
| }
|
| +
|
| + // If |current_input_method| is no longer in |active_input_method_ids|,
|
| + // switch to the first one in |active_input_method_ids|.
|
| + ChangeInputMethod(current_input_method.id(), false);
|
| }
|
|
|
| -void InputMethodManagerImpl::GetInputMethodExtensions(
|
| +void InputMethodManagerImpl::StateImpl::GetInputMethodExtensions(
|
| InputMethodDescriptors* result) {
|
| // Build the extension input method descriptors from the extra input
|
| - // methods cache |extra_input_methods_|.
|
| + // methods cache |extra_input_methods|.
|
| std::map<std::string, InputMethodDescriptor>::iterator iter;
|
| - for (iter = extra_input_methods_.begin(); iter != extra_input_methods_.end();
|
| + for (iter = extra_input_methods.begin(); iter != extra_input_methods.end();
|
| ++iter) {
|
| if (extension_ime_util::IsExtensionIME(iter->first))
|
| result->push_back(iter->second);
|
| }
|
| }
|
|
|
| -void InputMethodManagerImpl::SetEnabledExtensionImes(
|
| +void InputMethodManagerImpl::StateImpl::SetEnabledExtensionImes(
|
| std::vector<std::string>* ids) {
|
| - enabled_extension_imes_.clear();
|
| - enabled_extension_imes_.insert(enabled_extension_imes_.end(),
|
| - ids->begin(),
|
| - ids->end());
|
| -
|
| + enabled_extension_imes.clear();
|
| + enabled_extension_imes.insert(
|
| + enabled_extension_imes.end(), ids->begin(), ids->end());
|
| bool active_imes_changed = false;
|
| bool switch_to_pending = false;
|
|
|
| for (std::map<std::string, InputMethodDescriptor>::iterator extra_iter =
|
| - extra_input_methods_.begin(); extra_iter != extra_input_methods_.end();
|
| + extra_input_methods.begin();
|
| + extra_iter != extra_input_methods.end();
|
| ++extra_iter) {
|
| - if (extension_ime_util::IsComponentExtensionIME(
|
| - extra_iter->first))
|
| + if (extension_ime_util::IsComponentExtensionIME(extra_iter->first))
|
| continue; // Do not filter component extension.
|
|
|
| - if (pending_input_method_id_ == extra_iter->first)
|
| + if (pending_input_method_id == extra_iter->first)
|
| switch_to_pending = true;
|
|
|
| - std::vector<std::string>::iterator active_iter = std::find(
|
| - active_input_method_ids_.begin(), active_input_method_ids_.end(),
|
| - extra_iter->first);
|
| + std::vector<std::string>::iterator active_iter =
|
| + std::find(active_input_method_ids.begin(),
|
| + active_input_method_ids.end(),
|
| + extra_iter->first);
|
|
|
| - bool active = active_iter != active_input_method_ids_.end();
|
| - bool enabled = Contains(enabled_extension_imes_, extra_iter->first);
|
| + bool active = active_iter != active_input_method_ids.end();
|
| + bool enabled = Contains(enabled_extension_imes, extra_iter->first);
|
|
|
| if (active && !enabled)
|
| - active_input_method_ids_.erase(active_iter);
|
| + active_input_method_ids.erase(active_iter);
|
|
|
| if (!active && enabled)
|
| - active_input_method_ids_.push_back(extra_iter->first);
|
| + active_input_method_ids.push_back(extra_iter->first);
|
|
|
| if (active == !enabled)
|
| active_imes_changed = true;
|
| }
|
|
|
| - if (active_imes_changed) {
|
| - MaybeInitializeCandidateWindowController();
|
| + if (IsActive() && active_imes_changed) {
|
| + manager_->MaybeInitializeCandidateWindowController();
|
|
|
| if (switch_to_pending) {
|
| - ChangeInputMethod(pending_input_method_id_);
|
| - pending_input_method_id_.clear();
|
| + ChangeInputMethod(pending_input_method_id, false);
|
| + pending_input_method_id.clear();
|
| } else {
|
| // If |current_input_method| is no longer in |active_input_method_ids_|,
|
| // switch to the first one in |active_input_method_ids_|.
|
| - ChangeInputMethod(current_input_method_.id());
|
| + ChangeInputMethod(current_input_method.id(), false);
|
| }
|
| }
|
| }
|
|
|
| -void InputMethodManagerImpl::SetInputMethodLoginDefaultFromVPD(
|
| - const std::string& locale, const std::string& oem_layout) {
|
| +void InputMethodManagerImpl::StateImpl::SetInputMethodLoginDefaultFromVPD(
|
| + const std::string& locale,
|
| + const std::string& oem_layout) {
|
| std::string layout;
|
| if (!oem_layout.empty()) {
|
| // If the OEM layout information is provided, use it.
|
| @@ -596,10 +521,10 @@ void InputMethodManagerImpl::SetInputMethodLoginDefaultFromVPD(
|
| } else {
|
| // Otherwise, determine the hardware keyboard from the locale.
|
| std::vector<std::string> input_method_ids;
|
| - if (util_.GetInputMethodIdsFromLanguageCode(
|
| - locale,
|
| - chromeos::input_method::kKeyboardLayoutsOnly,
|
| - &input_method_ids)) {
|
| + if (manager_->util_.GetInputMethodIdsFromLanguageCode(
|
| + locale,
|
| + chromeos::input_method::kKeyboardLayoutsOnly,
|
| + &input_method_ids)) {
|
| // The output list |input_method_ids| is sorted by popularity, hence
|
| // input_method_ids[0] now contains the most popular keyboard layout
|
| // for the given locale.
|
| @@ -613,7 +538,7 @@ void InputMethodManagerImpl::SetInputMethodLoginDefaultFromVPD(
|
|
|
| std::vector<std::string> layouts;
|
| base::SplitString(layout, ',', &layouts);
|
| - MigrateInputMethods(&layouts);
|
| + manager_->MigrateInputMethods(&layouts);
|
|
|
| PrefService* prefs = g_browser_process->local_state();
|
| prefs->SetString(prefs::kHardwareKeyboardLayout, JoinString(layouts, ","));
|
| @@ -624,13 +549,13 @@ void InputMethodManagerImpl::SetInputMethodLoginDefaultFromVPD(
|
| // yet saved to disk.
|
| prefs->CommitPendingWrite();
|
|
|
| - util_.UpdateHardwareLayoutCache();
|
| + manager_->util_.UpdateHardwareLayoutCache();
|
|
|
| EnableLoginLayouts(locale, layouts);
|
| - LoadNecessaryComponentExtensions();
|
| + manager_->LoadNecessaryComponentExtensions(this);
|
| }
|
|
|
| -void InputMethodManagerImpl::SetInputMethodLoginDefault() {
|
| +void InputMethodManagerImpl::StateImpl::SetInputMethodLoginDefault() {
|
| // Set up keyboards. For example, when |locale| is "en-US", enable US qwerty
|
| // and US dvorak keyboard layouts.
|
| if (g_browser_process && g_browser_process->local_state()) {
|
| @@ -642,75 +567,77 @@ void InputMethodManagerImpl::SetInputMethodLoginDefault() {
|
| std::vector<std::string> input_methods_to_be_enabled;
|
| if (initial_input_method_id.empty()) {
|
| // If kPreferredKeyboardLayout is not specified, use the hardware layout.
|
| - input_methods_to_be_enabled = util_.GetHardwareLoginInputMethodIds();
|
| + input_methods_to_be_enabled =
|
| + manager_->util_.GetHardwareLoginInputMethodIds();
|
| } else {
|
| input_methods_to_be_enabled.push_back(initial_input_method_id);
|
| }
|
| EnableLoginLayouts(locale, input_methods_to_be_enabled);
|
| - LoadNecessaryComponentExtensions();
|
| + manager_->LoadNecessaryComponentExtensions(this);
|
| }
|
| }
|
|
|
| -bool InputMethodManagerImpl::SwitchToNextInputMethod() {
|
| +bool InputMethodManagerImpl::StateImpl::SwitchToNextInputMethod() {
|
| // Sanity checks.
|
| - if (active_input_method_ids_.empty()) {
|
| + if (active_input_method_ids.empty()) {
|
| DVLOG(1) << "active input method is empty";
|
| return false;
|
| }
|
|
|
| - if (current_input_method_.id().empty()) {
|
| - DVLOG(1) << "current_input_method_ is unknown";
|
| + if (current_input_method.id().empty()) {
|
| + DVLOG(1) << "current_input_method is unknown";
|
| return false;
|
| }
|
|
|
| // Do not consume key event if there is only one input method is enabled.
|
| // Ctrl+Space or Alt+Shift may be used by other application.
|
| - if (active_input_method_ids_.size() == 1)
|
| + if (active_input_method_ids.size() == 1)
|
| return false;
|
|
|
| // Find the next input method and switch to it.
|
| - SwitchToNextInputMethodInternal(active_input_method_ids_,
|
| - current_input_method_.id());
|
| + SwitchToNextInputMethodInternal(active_input_method_ids,
|
| + current_input_method.id());
|
| return true;
|
| }
|
|
|
| -bool InputMethodManagerImpl::SwitchToPreviousInputMethod(
|
| +bool InputMethodManagerImpl::StateImpl::SwitchToPreviousInputMethod(
|
| const ui::Accelerator& accelerator) {
|
| // Sanity check.
|
| - if (active_input_method_ids_.empty()) {
|
| + if (active_input_method_ids.empty()) {
|
| DVLOG(1) << "active input method is empty";
|
| return false;
|
| }
|
|
|
| // Do not consume key event if there is only one input method is enabled.
|
| // Ctrl+Space or Alt+Shift may be used by other application.
|
| - if (active_input_method_ids_.size() == 1)
|
| + if (active_input_method_ids.size() == 1)
|
| return false;
|
|
|
| if (accelerator.type() == ui::ET_KEY_RELEASED)
|
| return true;
|
|
|
| - if (previous_input_method_.id().empty() ||
|
| - previous_input_method_.id() == current_input_method_.id()) {
|
| + if (previous_input_method.id().empty() ||
|
| + previous_input_method.id() == current_input_method.id()) {
|
| return SwitchToNextInputMethod();
|
| }
|
|
|
| std::vector<std::string>::const_iterator iter =
|
| - std::find(active_input_method_ids_.begin(),
|
| - active_input_method_ids_.end(),
|
| - previous_input_method_.id());
|
| - if (iter == active_input_method_ids_.end()) {
|
| - // previous_input_method_ is not supported.
|
| + std::find(active_input_method_ids.begin(),
|
| + active_input_method_ids.end(),
|
| + previous_input_method.id());
|
| + if (iter == active_input_method_ids.end()) {
|
| + // previous_input_method is not supported.
|
| return SwitchToNextInputMethod();
|
| }
|
| - ChangeInputMethodInternal(*iter, true);
|
| + ChangeInputMethod(*iter, true);
|
| +
|
| return true;
|
| }
|
|
|
| -bool InputMethodManagerImpl::SwitchInputMethod(
|
| +bool InputMethodManagerImpl::StateImpl::SwitchInputMethod(
|
| const ui::Accelerator& accelerator) {
|
| // Sanity check.
|
| - if (active_input_method_ids_.empty()) {
|
| + if (active_input_method_ids.empty()) {
|
| DVLOG(1) << "active input method is empty";
|
| return false;
|
| }
|
| @@ -744,12 +671,12 @@ bool InputMethodManagerImpl::SwitchInputMethod(
|
| }
|
|
|
| // Obtain the intersection of input_method_ids_to_switch and
|
| - // active_input_method_ids_. The order of IDs in active_input_method_ids_ is
|
| + // active_input_method_ids. The order of IDs in active_input_method_ids is
|
| // preserved.
|
| std::vector<std::string> ids;
|
| for (size_t i = 0; i < input_method_ids_to_switch.size(); ++i) {
|
| const std::string& id = input_method_ids_to_switch[i];
|
| - if (Contains(active_input_method_ids_, id))
|
| + if (Contains(active_input_method_ids, id))
|
| ids.push_back(id);
|
| }
|
| if (ids.empty()) {
|
| @@ -758,29 +685,291 @@ bool InputMethodManagerImpl::SwitchInputMethod(
|
| return false;
|
| }
|
|
|
| - SwitchToNextInputMethodInternal(ids, current_input_method_.id());
|
| + SwitchToNextInputMethodInternal(ids, current_input_method.id());
|
| return true; // consume the accelerator.
|
| }
|
|
|
| -void InputMethodManagerImpl::SwitchToNextInputMethodInternal(
|
| +void InputMethodManagerImpl::StateImpl::SwitchToNextInputMethodInternal(
|
| const std::vector<std::string>& input_method_ids,
|
| - const std::string& current_input_method_id) {
|
| - std::vector<std::string>::const_iterator iter =
|
| - std::find(input_method_ids.begin(),
|
| - input_method_ids.end(),
|
| - current_input_method_id);
|
| + const std::string& current_input_methodid) {
|
| + std::vector<std::string>::const_iterator iter = std::find(
|
| + input_method_ids.begin(), input_method_ids.end(), current_input_methodid);
|
| if (iter != input_method_ids.end())
|
| ++iter;
|
| if (iter == input_method_ids.end())
|
| iter = input_method_ids.begin();
|
| - ChangeInputMethodInternal(*iter, true);
|
| + ChangeInputMethod(*iter, true);
|
| }
|
|
|
| -InputMethodDescriptor InputMethodManagerImpl::GetCurrentInputMethod() const {
|
| - if (current_input_method_.id().empty())
|
| +InputMethodDescriptor InputMethodManagerImpl::StateImpl::GetCurrentInputMethod()
|
| + const {
|
| + if (current_input_method.id().empty())
|
| return InputMethodUtil::GetFallbackInputMethodDescriptor();
|
|
|
| - return current_input_method_;
|
| + return current_input_method;
|
| +}
|
| +
|
| +bool InputMethodManagerImpl::StateImpl::InputMethodIsActivated(
|
| + const std::string& input_method_id) const {
|
| + return Contains(active_input_method_ids, input_method_id);
|
| +}
|
| +
|
| +// ------------------------ InputMethodManagerImpl
|
| +bool InputMethodManagerImpl::IsLoginKeyboard(
|
| + const std::string& layout) const {
|
| + return util_.IsLoginKeyboard(layout);
|
| +}
|
| +
|
| +bool InputMethodManagerImpl::MigrateInputMethods(
|
| + std::vector<std::string>* input_method_ids) {
|
| + return util_.MigrateInputMethods(input_method_ids);
|
| +}
|
| +
|
| +// Starts or stops the system input method framework as needed.
|
| +void InputMethodManagerImpl::ReconfigureIMFramework(
|
| + InputMethodManagerImpl::StateImpl* state) {
|
| + LoadNecessaryComponentExtensions(state);
|
| +
|
| + // Initialize candidate window controller and widgets such as
|
| + // candidate window, infolist and mode indicator. Note, mode
|
| + // indicator is used by only keyboard layout input methods.
|
| + if (state_.get() == state)
|
| + MaybeInitializeCandidateWindowController();
|
| +}
|
| +
|
| +void InputMethodManagerImpl::SetState(
|
| + scoped_refptr<InputMethodManager::State> state) {
|
| + DCHECK(state);
|
| + InputMethodManagerImpl::StateImpl* new_impl_state =
|
| + static_cast<InputMethodManagerImpl::StateImpl*>(state.get());
|
| + const bool need_update_current_input_method =
|
| + (state_ ? state_->current_input_method.id() !=
|
| + new_impl_state->current_input_method.id()
|
| + : true);
|
| + state_ = new_impl_state;
|
| +
|
| + if (state_ && state_->active_input_method_ids.size()) {
|
| + // Initialize candidate window controller and widgets such as
|
| + // candidate window, infolist and mode indicator. Note, mode
|
| + // indicator is used by only keyboard layout input methods.
|
| + MaybeInitializeCandidateWindowController();
|
| +
|
| + if (need_update_current_input_method)
|
| + ChangeInputMethodInternal(state_->current_input_method,
|
| + false /* show_message */,
|
| + true /* notify_menu */);
|
| + }
|
| +}
|
| +
|
| +scoped_refptr<InputMethodManager::State>
|
| +InputMethodManagerImpl::GetActiveIMEState() {
|
| + return scoped_refptr<InputMethodManager::State>(state_.get());
|
| +}
|
| +
|
| +InputMethodManagerImpl::InputMethodManagerImpl(
|
| + scoped_ptr<InputMethodDelegate> delegate,
|
| + bool enable_extension_loading)
|
| + : delegate_(delegate.Pass()),
|
| + ui_session_(STATE_LOGIN_SCREEN),
|
| + state_(NULL),
|
| + util_(delegate_.get()),
|
| + component_extension_ime_manager_(new ComponentExtensionIMEManager()),
|
| + enable_extension_loading_(enable_extension_loading) {
|
| + if (base::SysInfo::IsRunningOnChromeOS())
|
| + keyboard_.reset(ImeKeyboard::Create());
|
| + else
|
| + keyboard_.reset(new FakeImeKeyboard());
|
| +
|
| + // Initializes the system IME list.
|
| + scoped_ptr<ComponentExtensionIMEManagerDelegate> comp_delegate(
|
| + new ComponentExtensionIMEManagerImpl());
|
| + component_extension_ime_manager_->Initialize(comp_delegate.Pass());
|
| + util_.ResetInputMethods(
|
| + component_extension_ime_manager_->GetAllIMEAsInputMethodDescriptor());
|
| +}
|
| +
|
| +InputMethodManagerImpl::~InputMethodManagerImpl() {
|
| + if (candidate_window_controller_.get())
|
| + candidate_window_controller_->RemoveObserver(this);
|
| +}
|
| +
|
| +void InputMethodManagerImpl::AddObserver(
|
| + InputMethodManager::Observer* observer) {
|
| + observers_.AddObserver(observer);
|
| +}
|
| +
|
| +void InputMethodManagerImpl::AddCandidateWindowObserver(
|
| + InputMethodManager::CandidateWindowObserver* observer) {
|
| + candidate_window_observers_.AddObserver(observer);
|
| +}
|
| +
|
| +void InputMethodManagerImpl::RemoveObserver(
|
| + InputMethodManager::Observer* observer) {
|
| + observers_.RemoveObserver(observer);
|
| +}
|
| +
|
| +void InputMethodManagerImpl::RemoveCandidateWindowObserver(
|
| + InputMethodManager::CandidateWindowObserver* observer) {
|
| + candidate_window_observers_.RemoveObserver(observer);
|
| +}
|
| +
|
| +InputMethodManager::UISessionState InputMethodManagerImpl::GetUISessionState() {
|
| + return ui_session_;
|
| +}
|
| +
|
| +void InputMethodManagerImpl::SetUISessionState(UISessionState new_ui_session) {
|
| + ui_session_ = new_ui_session;
|
| + switch (ui_session_) {
|
| + case STATE_LOGIN_SCREEN:
|
| + break;
|
| + case STATE_BROWSER_SCREEN:
|
| + break;
|
| + case STATE_LOCK_SCREEN:
|
| + break;
|
| + case STATE_TERMINATING: {
|
| + if (candidate_window_controller_.get())
|
| + candidate_window_controller_.reset();
|
| + break;
|
| + }
|
| + }
|
| +}
|
| +
|
| +scoped_ptr<InputMethodDescriptors>
|
| +InputMethodManagerImpl::GetSupportedInputMethods() const {
|
| + return scoped_ptr<InputMethodDescriptors>(new InputMethodDescriptors).Pass();
|
| +}
|
| +
|
| +const InputMethodDescriptor* InputMethodManagerImpl::LookupInputMethod(
|
| + const std::string& input_method_id,
|
| + InputMethodManagerImpl::StateImpl* state) {
|
| + DCHECK(state);
|
| +
|
| + std::string input_method_id_to_switch = input_method_id;
|
| +
|
| + // Sanity check
|
| + if (!state->InputMethodIsActivated(input_method_id)) {
|
| + scoped_ptr<InputMethodDescriptors> input_methods(
|
| + state->GetActiveInputMethods());
|
| + DCHECK(!input_methods->empty());
|
| + input_method_id_to_switch = input_methods->at(0).id();
|
| + if (!input_method_id.empty()) {
|
| + DVLOG(1) << "Can't change the current input method to "
|
| + << input_method_id << " since the engine is not enabled. "
|
| + << "Switch to " << input_method_id_to_switch << " instead.";
|
| + }
|
| + }
|
| +
|
| + const InputMethodDescriptor* descriptor = NULL;
|
| + if (extension_ime_util::IsExtensionIME(input_method_id_to_switch)) {
|
| + DCHECK(state->extra_input_methods.find(input_method_id_to_switch) !=
|
| + state->extra_input_methods.end());
|
| + descriptor = &(state->extra_input_methods[input_method_id_to_switch]);
|
| + } else {
|
| + descriptor =
|
| + util_.GetInputMethodDescriptorFromId(input_method_id_to_switch);
|
| + if (!descriptor)
|
| + LOG(ERROR) << "Unknown input method id: " << input_method_id_to_switch;
|
| + }
|
| + DCHECK(descriptor);
|
| + return descriptor;
|
| +}
|
| +
|
| +void InputMethodManagerImpl::ChangeInputMethodInternal(
|
| + const InputMethodDescriptor& descriptor,
|
| + bool show_message,
|
| + bool notify_menu) {
|
| + // No need to switch input method when terminating.
|
| + if (ui_session_ == STATE_TERMINATING)
|
| + return;
|
| +
|
| + if (candidate_window_controller_.get())
|
| + candidate_window_controller_->Hide();
|
| +
|
| + if (notify_menu) {
|
| + // Clear property list. Property list would be updated by
|
| + // extension IMEs via InputMethodEngine::(Set|Update)MenuItems.
|
| + // If the current input method is a keyboard layout, empty
|
| + // properties are sufficient.
|
| + const ash::ime::InputMethodMenuItemList empty_menu_item_list;
|
| + ash::ime::InputMethodMenuManager* input_method_menu_manager =
|
| + ash::ime::InputMethodMenuManager::GetInstance();
|
| + input_method_menu_manager->SetCurrentInputMethodMenuItemList(
|
| + empty_menu_item_list);
|
| + }
|
| +
|
| + // Disable the current engine handler.
|
| + IMEEngineHandlerInterface* engine =
|
| + IMEBridge::Get()->GetCurrentEngineHandler();
|
| + if (engine)
|
| + engine->Disable();
|
| +
|
| + // Configure the next engine handler.
|
| + // This must be after |current_input_method| has been set to new input
|
| + // method, because engine's Enable() method needs to access it.
|
| + const std::string& extension_id =
|
| + extension_ime_util::GetExtensionIDFromInputMethodID(descriptor.id());
|
| + const std::string& component_id =
|
| + extension_ime_util::GetComponentIDByInputMethodID(descriptor.id());
|
| + engine = engine_map_[extension_id];
|
| +
|
| + IMEBridge::Get()->SetCurrentEngineHandler(engine);
|
| +
|
| + if (engine)
|
| + engine->Enable(component_id);
|
| +
|
| + // Change the keyboard layout to a preferred layout for the input method.
|
| + if (!keyboard_->SetCurrentKeyboardLayoutByName(
|
| + descriptor.GetPreferredKeyboardLayout())) {
|
| + LOG(ERROR) << "Failed to change keyboard layout to "
|
| + << descriptor.GetPreferredKeyboardLayout();
|
| + }
|
| +
|
| + // Update input method indicators (e.g. "US", "DV") in Chrome windows.
|
| + FOR_EACH_OBSERVER(InputMethodManager::Observer,
|
| + observers_,
|
| + InputMethodChanged(this, show_message));
|
| +}
|
| +
|
| +void InputMethodManagerImpl::LoadNecessaryComponentExtensions(
|
| + InputMethodManagerImpl::StateImpl* state) {
|
| + // Load component extensions but also update |active_input_method_ids| as
|
| + // some component extension IMEs may have been removed from the Chrome OS
|
| + // image. If specified component extension IME no longer exists, falling back
|
| + // to an existing IME.
|
| + DCHECK(state);
|
| + std::vector<std::string> unfiltered_input_method_ids;
|
| + unfiltered_input_method_ids.swap(state->active_input_method_ids);
|
| + for (size_t i = 0; i < unfiltered_input_method_ids.size(); ++i) {
|
| + if (!extension_ime_util::IsComponentExtensionIME(
|
| + unfiltered_input_method_ids[i])) {
|
| + // Legacy IMEs or xkb layouts are alwayes active.
|
| + state->active_input_method_ids.push_back(unfiltered_input_method_ids[i]);
|
| + } else if (component_extension_ime_manager_->IsWhitelisted(
|
| + unfiltered_input_method_ids[i])) {
|
| + if (enable_extension_loading_) {
|
| + component_extension_ime_manager_->LoadComponentExtensionIME(
|
| + state->profile, unfiltered_input_method_ids[i]);
|
| + }
|
| +
|
| + state->active_input_method_ids.push_back(unfiltered_input_method_ids[i]);
|
| + }
|
| + }
|
| +}
|
| +
|
| +void InputMethodManagerImpl::ActivateInputMethodMenuItem(
|
| + const std::string& key) {
|
| + DCHECK(!key.empty());
|
| +
|
| + if (ash::ime::InputMethodMenuManager::GetInstance()->
|
| + HasInputMethodMenuItemForKey(key)) {
|
| + IMEEngineHandlerInterface* engine =
|
| + IMEBridge::Get()->GetCurrentEngineHandler();
|
| + if (engine)
|
| + engine->PropertyActivate(key);
|
| + return;
|
| + }
|
| +
|
| + DVLOG(1) << "ActivateInputMethodMenuItem: unknown key: " << key;
|
| }
|
|
|
| bool InputMethodManagerImpl::IsISOLevel5ShiftUsedByCurrentInputMethod() const {
|
| @@ -804,6 +993,11 @@ ComponentExtensionIMEManager*
|
| return component_extension_ime_manager_.get();
|
| }
|
|
|
| +scoped_refptr<InputMethodManager::State> InputMethodManagerImpl::CreateNewState(
|
| + Profile* profile) {
|
| + return scoped_refptr<InputMethodManager::State>(new StateImpl(this, profile));
|
| +}
|
| +
|
| void InputMethodManagerImpl::SetCandidateWindowControllerForTesting(
|
| CandidateWindowController* candidate_window_controller) {
|
| candidate_window_controller_.reset(candidate_window_controller);
|
| @@ -840,54 +1034,6 @@ void InputMethodManagerImpl::CandidateWindowClosed() {
|
| CandidateWindowClosed(this));
|
| }
|
|
|
| -void InputMethodManagerImpl::OnScreenLocked() {
|
| - saved_previous_input_method_ = previous_input_method_;
|
| - saved_current_input_method_ = current_input_method_;
|
| - saved_active_input_method_ids_ = active_input_method_ids_;
|
| -
|
| - std::set<std::string> added_ids_;
|
| -
|
| - const std::vector<std::string>& hardware_keyboard_ids =
|
| - util_.GetHardwareLoginInputMethodIds();
|
| -
|
| - active_input_method_ids_.clear();
|
| - for (size_t i = 0; i < saved_active_input_method_ids_.size(); ++i) {
|
| - const std::string& input_method_id = saved_active_input_method_ids_[i];
|
| - // Skip if it's not a keyboard layout. Drop input methods including
|
| - // extension ones.
|
| - if (!IsLoginKeyboard(input_method_id) ||
|
| - added_ids_.find(input_method_id) != added_ids_.end())
|
| - continue;
|
| - active_input_method_ids_.push_back(input_method_id);
|
| - added_ids_.insert(input_method_id);
|
| - }
|
| -
|
| - // We'll add the hardware keyboard if it's not included in
|
| - // |active_input_method_ids_| so that the user can always use the hardware
|
| - // keyboard on the screen locker.
|
| - for (size_t i = 0; i < hardware_keyboard_ids.size(); ++i) {
|
| - if (added_ids_.find(hardware_keyboard_ids[i]) == added_ids_.end()) {
|
| - active_input_method_ids_.push_back(hardware_keyboard_ids[i]);
|
| - added_ids_.insert(hardware_keyboard_ids[i]);
|
| - }
|
| - }
|
| -
|
| - ChangeInputMethod(current_input_method_.id());
|
| -}
|
| -
|
| -void InputMethodManagerImpl::OnScreenUnlocked() {
|
| - previous_input_method_ = saved_previous_input_method_;
|
| - current_input_method_ = saved_current_input_method_;
|
| - active_input_method_ids_ = saved_active_input_method_ids_;
|
| -
|
| - ChangeInputMethod(current_input_method_.id());
|
| -}
|
| -
|
| -bool InputMethodManagerImpl::InputMethodIsActivated(
|
| - const std::string& input_method_id) {
|
| - return Contains(active_input_method_ids_, input_method_id);
|
| -}
|
| -
|
| void InputMethodManagerImpl::MaybeInitializeCandidateWindowController() {
|
| if (candidate_window_controller_.get())
|
| return;
|
|
|