| Index: chrome/browser/chromeos/input_method/input_method_manager.cc
|
| diff --git a/chrome/browser/chromeos/input_method/input_method_manager.cc b/chrome/browser/chromeos/input_method/input_method_manager.cc
|
| index 8159e149c8f8e528b936dadf79d1a8d5460011f6..54ae26b921a22f86e156cb4c5cf8d3476ae3808c 100644
|
| --- a/chrome/browser/chromeos/input_method/input_method_manager.cc
|
| +++ b/chrome/browser/chromeos/input_method/input_method_manager.cc
|
| @@ -4,1277 +4,43 @@
|
|
|
| #include "chrome/browser/chromeos/input_method/input_method_manager.h"
|
|
|
| -#include <algorithm>
|
| -
|
| -#include <glib.h>
|
| -
|
| -#include "base/basictypes.h"
|
| -#include "base/memory/scoped_ptr.h"
|
| -#include "base/memory/singleton.h"
|
| -#include "base/message_loop.h"
|
| -#include "base/process_util.h"
|
| -#include "base/string_split.h"
|
| -#include "base/string_util.h"
|
| -#include "base/stringprintf.h"
|
| -#include "chrome/browser/browser_process.h"
|
| -#include "chrome/browser/chromeos/input_method/browser_state_monitor.h"
|
| -#include "chrome/browser/chromeos/input_method/input_method_util.h"
|
| -#include "chrome/browser/chromeos/input_method/input_method_whitelist.h"
|
| -#include "chrome/browser/chromeos/input_method/virtual_keyboard_selector.h"
|
| -#include "chrome/browser/chromeos/input_method/xkeyboard.h"
|
| -#include "chrome/browser/chromeos/language_preferences.h"
|
| -#include "content/public/browser/browser_thread.h"
|
| -#include "content/public/browser/notification_observer.h"
|
| -#include "content/public/browser/notification_registrar.h"
|
| -#include "content/public/browser/notification_service.h"
|
| -#include "content/public/browser/notification_types.h"
|
| -#include "googleurl/src/gurl.h"
|
| -#include "ui/base/accelerators/accelerator.h"
|
| -#include "unicode/uloc.h"
|
| -
|
| -#if !defined(USE_VIRTUAL_KEYBOARD)
|
| -#include "chrome/browser/chromeos/input_method/candidate_window.h"
|
| -#endif
|
| -
|
| -#if defined(HAVE_IBUS)
|
| -#include <ibus.h>
|
| -#endif
|
| -
|
| -using content::BrowserThread;
|
| -
|
| -namespace {
|
| -
|
| -const char kIBusDaemonPath[] = "/usr/bin/ibus-daemon";
|
| -
|
| -// Finds a property which has |new_prop.key| from |prop_list|, and replaces the
|
| -// property with |new_prop|. Returns true if such a property is found.
|
| -bool FindAndUpdateProperty(
|
| - const chromeos::input_method::InputMethodProperty& new_prop,
|
| - chromeos::input_method::InputMethodPropertyList* prop_list) {
|
| - for (size_t i = 0; i < prop_list->size(); ++i) {
|
| - chromeos::input_method::InputMethodProperty& prop = prop_list->at(i);
|
| - if (prop.key == new_prop.key) {
|
| - const int saved_id = prop.selection_item_id;
|
| - // Update the list except the radio id. As written in
|
| - // chromeos_input_method.h, |prop.selection_item_id| is dummy.
|
| - prop = new_prop;
|
| - prop.selection_item_id = saved_id;
|
| - return true;
|
| - }
|
| - }
|
| - return false;
|
| -}
|
| -
|
| -} // namespace
|
| +#include "chrome/browser/chromeos/input_method/input_method_manager_impl.h"
|
|
|
| namespace chromeos {
|
| namespace input_method {
|
|
|
| -// The implementation of InputMethodManager.
|
| -class InputMethodManagerImpl : public InputMethodManager,
|
| - public content::NotificationObserver,
|
| -#if !defined(USE_VIRTUAL_KEYBOARD)
|
| - public CandidateWindowController::Observer,
|
| -#endif
|
| - public IBusController::Observer {
|
| - public:
|
| - InputMethodManagerImpl()
|
| - : ibus_controller_(IBusController::Create()),
|
| - should_hide_properties_(true),
|
| - should_launch_ime_(false),
|
| - ime_connected_(false),
|
| - enable_auto_ime_shutdown_(false), // workaround for crosbug.com/27051.
|
| - enable_extension_imes_(true),
|
| - shutting_down_(false),
|
| - ibus_daemon_process_handle_(base::kNullProcessHandle),
|
| - util_(whitelist_.GetSupportedInputMethods()),
|
| - xkeyboard_(XKeyboard::Create(util_)),
|
| - ALLOW_THIS_IN_INITIALIZER_LIST(
|
| - browser_state_monitor_(new BrowserStateMonitor(this))),
|
| - ignore_hotkeys_(false) {
|
| - // Observe APP_TERMINATING to stop input method daemon gracefully.
|
| - // We should not use APP_EXITING here since logout might be canceled by
|
| - // JavaScript after APP_EXITING is sent (crosbug.com/11055).
|
| - // Note that even if we fail to stop input method daemon from
|
| - // Chrome in case of a sudden crash, we have a way to do it from an
|
| - // upstart script. See crosbug.com/6515 and crosbug.com/6995 for
|
| - // details.
|
| - notification_registrar_.Add(this, content::NOTIFICATION_APP_TERMINATING,
|
| - content::NotificationService::AllSources());
|
| -
|
| - // The observer should be added before Connect() so we can capture the
|
| - // initial connection change.
|
| - ibus_controller_->AddObserver(this);
|
| - ibus_controller_->Connect();
|
| -
|
| - EnableHotkeys();
|
| - }
|
| -
|
| - virtual ~InputMethodManagerImpl() {
|
| - ibus_controller_->RemoveObserver(this);
|
| -#if !defined(USE_VIRTUAL_KEYBOARD)
|
| - if (candidate_window_controller_.get())
|
| - candidate_window_controller_->RemoveObserver(this);
|
| -#endif
|
| - }
|
| -
|
| - virtual void AddObserver(InputMethodManager::Observer* observer) {
|
| - observers_.AddObserver(observer);
|
| - }
|
| -
|
| - virtual void RemoveObserver(InputMethodManager::Observer* observer) {
|
| - observers_.RemoveObserver(observer);
|
| - }
|
| -
|
| - virtual void AddCandidateWindowObserver(
|
| - InputMethodManager::CandidateWindowObserver* observer) {
|
| - candidate_window_observers_.AddObserver(observer);
|
| - }
|
| -
|
| - virtual void RemoveCandidateWindowObserver(
|
| - InputMethodManager::CandidateWindowObserver* observer) {
|
| - candidate_window_observers_.RemoveObserver(observer);
|
| - }
|
| -
|
| - virtual void AddVirtualKeyboardObserver(VirtualKeyboardObserver* observer) {
|
| - virtual_keyboard_observers_.AddObserver(observer);
|
| - }
|
| -
|
| - virtual void RemoveVirtualKeyboardObserver(
|
| - VirtualKeyboardObserver* observer) {
|
| - virtual_keyboard_observers_.RemoveObserver(observer);
|
| - }
|
| -
|
| - virtual InputMethodDescriptors* GetActiveInputMethods() {
|
| - 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];
|
| - const InputMethodDescriptor* descriptor =
|
| - util_.GetInputMethodDescriptorFromId(input_method_id);
|
| - if (descriptor) {
|
| - result->push_back(*descriptor);
|
| - } else {
|
| - std::map<std::string, InputMethodDescriptor>::
|
| - const_iterator ix = extra_input_method_ids_.find(input_method_id);
|
| - if (ix != extra_input_method_ids_.end()) {
|
| - result->push_back(ix->second);
|
| - } else {
|
| - LOG(ERROR) << "Descriptor is not found for: " << input_method_id;
|
| - }
|
| - }
|
| - }
|
| - // Initially active_input_method_ids_ is empty. In this case, just
|
| - // returns the fallback input method descriptor.
|
| - if (result->empty()) {
|
| - // Since browser_tests call neither
|
| - // SetInputMethodConfig("preload_engines") nor EnableInputMethod(), this
|
| - // path might be taken.
|
| - result->push_back(
|
| - InputMethodDescriptor::GetFallbackInputMethodDescriptor());
|
| - }
|
| - return result;
|
| - }
|
| -
|
| - virtual size_t GetNumActiveInputMethods() {
|
| - scoped_ptr<InputMethodDescriptors> input_methods(GetActiveInputMethods());
|
| - return input_methods->size();
|
| - }
|
| -
|
| - virtual InputMethodDescriptors* GetSupportedInputMethods() {
|
| - return whitelist_.GetSupportedInputMethods();
|
| - }
|
| -
|
| - virtual void ChangeInputMethod(const std::string& input_method_id) {
|
| - // Changing the input method isn't guaranteed to succeed here, but we
|
| - // should remember the last one regardless. See comments in
|
| - // FlushImeConfig() for details.
|
| - tentative_current_input_method_id_ = input_method_id;
|
| -
|
| - if (InputMethodUtil::IsKeyboardLayout(input_method_id)) {
|
| - // We shouldn't use SetCurrentKeyboardLayoutByName() here. See
|
| - // comments at ChangeCurrentInputMethod() for details.
|
| - ChangeCurrentInputMethodFromId(input_method_id);
|
| - OnRegisterImeProperties(InputMethodPropertyList()); // notify the button.
|
| - } else {
|
| - // Otherwise, start the input method daemon, and change the input
|
| - // method via the daemon.
|
| - StartInputMethodDaemon();
|
| - // ChangeInputMethodViaIBus() fails if the IBus daemon is not
|
| - // ready yet. In this case, we'll defer the input method change
|
| - // until the daemon is ready.
|
| - if (!ChangeInputMethodViaIBus(input_method_id)) {
|
| - VLOG(1) << "Failed to change the input method to " << input_method_id
|
| - << " (deferring)";
|
| - }
|
| - }
|
| - }
|
| -
|
| - virtual void EnableLayouts(const std::string& language_code,
|
| - const std::string& initial_input_method_id) {
|
| - std::vector<std::string> candidates;
|
| - // Add input methods associated with the language.
|
| - util_.GetInputMethodIdsFromLanguageCode(language_code,
|
| - kKeyboardLayoutsOnly,
|
| - &candidates);
|
| - // Add the hardware keyboard as well. We should always add this so users
|
| - // can use the hardware keyboard on the login screen and the screen locker.
|
| - candidates.push_back(util_.GetHardwareInputMethodId());
|
| -
|
| - std::vector<std::string> input_method_ids;
|
| - // First, add the initial input method ID, if it's requested, to
|
| - // input_method_ids, so it appears first on the list of active input
|
| - // methods at the input language status menu.
|
| - if (!initial_input_method_id.empty()) {
|
| - input_method_ids.push_back(initial_input_method_id);
|
| - }
|
| -
|
| - // Add candidates to input_method_ids, while skipping duplicates.
|
| - for (size_t i = 0; i < candidates.size(); ++i) {
|
| - const std::string& candidate = candidates[i];
|
| - // Not efficient, but should be fine, as the two vectors are very
|
| - // short (2-5 items).
|
| - if (std::count(input_method_ids.begin(), input_method_ids.end(),
|
| - candidate) == 0) {
|
| - input_method_ids.push_back(candidate);
|
| - }
|
| - }
|
| -
|
| - // Update ibus-daemon setting. Here, we don't save the input method list
|
| - // in the user's preferences.
|
| - InputMethodConfigValue value;
|
| - value.type = InputMethodConfigValue::kValueTypeStringList;
|
| - value.string_list_value = input_method_ids;
|
| - SetInputMethodConfig(language_prefs::kGeneralSectionName,
|
| - language_prefs::kPreloadEnginesConfigName,
|
| - value);
|
| -
|
| - // Finaly, change to the initial input method, as needed.
|
| - if (!initial_input_method_id.empty()) {
|
| - ChangeInputMethod(initial_input_method_id);
|
| - }
|
| - }
|
| -
|
| - virtual void SetImePropertyActivated(const std::string& key,
|
| - bool activated) {
|
| - DCHECK(!key.empty());
|
| - ibus_controller_->SetImePropertyActivated(key, activated);
|
| - }
|
| -
|
| - virtual bool InputMethodIsActivated(const std::string& input_method_id) {
|
| - scoped_ptr<InputMethodDescriptors> active_input_method_descriptors(
|
| - GetActiveInputMethods());
|
| - for (size_t i = 0; i < active_input_method_descriptors->size(); ++i) {
|
| - if (active_input_method_descriptors->at(i).id() == input_method_id) {
|
| - return true;
|
| - }
|
| - }
|
| - return false;
|
| - }
|
| -
|
| - virtual bool SetInputMethodConfig(const std::string& section,
|
| - const std::string& config_name,
|
| - const InputMethodConfigValue& value) {
|
| - // If the config change is for preload engines, update the active
|
| - // input methods cache |active_input_method_ids_| here. We need to
|
| - // update the cache before actually flushing the config. since we need
|
| - // to return active input methods from GetActiveInputMethods() before
|
| - // the input method daemon starts. For instance, we need to show the
|
| - // list of available input methods (keyboard layouts) on the login
|
| - // screen before the input method starts.
|
| - if (section == language_prefs::kGeneralSectionName &&
|
| - config_name == language_prefs::kPreloadEnginesConfigName &&
|
| - value.type == InputMethodConfigValue::kValueTypeStringList) {
|
| - active_input_method_ids_ = value.string_list_value;
|
| -
|
| - if (enable_extension_imes_) {
|
| - std::map<std::string, InputMethodDescriptor>::const_iterator ix;
|
| - for (ix = extra_input_method_ids_.begin();
|
| - ix != extra_input_method_ids_.end(); ++ix) {
|
| - active_input_method_ids_.push_back(ix->first);
|
| - }
|
| - }
|
| - }
|
| -
|
| - // Before calling FlushImeConfig(), start input method process if necessary.
|
| - MaybeStartInputMethodDaemon(section, config_name, value);
|
| -
|
| - const ConfigKeyType key = std::make_pair(section, config_name);
|
| - current_config_values_[key] = value;
|
| - if (ime_connected_) {
|
| - pending_config_requests_[key] = value;
|
| - FlushImeConfig();
|
| - }
|
| -
|
| - if (section == language_prefs::kGeneralSectionName &&
|
| - config_name == language_prefs::kPreloadEnginesConfigName) {
|
| - // Stop input method process if necessary.
|
| - MaybeStopInputMethodDaemon();
|
| - }
|
| - // Change the current keyboard layout if necessary.
|
| - MaybeChangeCurrentKeyboardLayout(section, config_name, value);
|
| - return pending_config_requests_.empty();
|
| - }
|
| -
|
| - // TODO(yusukes): Support input method specific hotkeys.
|
| - virtual void AddActiveIme(const std::string& id,
|
| - const std::string& name,
|
| - const std::vector<std::string>& layouts,
|
| - const std::string& language) {
|
| - std::string virtual_layouts = JoinString(layouts, ',');
|
| -
|
| - extra_input_method_ids_[id] = ibus_controller_->CreateInputMethodDescriptor(
|
| - id, name, virtual_layouts, language);
|
| - active_input_method_ids_.push_back(id);
|
| -
|
| - // Ensure that the input method daemon is running.
|
| - StartInputMethodDaemon();
|
| - }
|
| -
|
| - virtual void RemoveActiveIme(const std::string& id) {
|
| - std::vector<std::string>::iterator ix =
|
| - std::find(active_input_method_ids_.begin(),
|
| - active_input_method_ids_.end(),
|
| - id);
|
| - if (ix != active_input_method_ids_.end()) {
|
| - active_input_method_ids_.erase(ix);
|
| - // TODO(yusukes): this is a workaround for crosbug.com/27051. Uncomment
|
| - // this when the bug is fixed.
|
| - if (!active_input_method_ids_.empty()) {
|
| - ChangeInputMethod(active_input_method_ids_[0]);
|
| - }
|
| - }
|
| - extra_input_method_ids_.erase(id);
|
| -
|
| - // Stop the IME daemon if needed.
|
| - MaybeStopInputMethodDaemon();
|
| - }
|
| -
|
| - virtual bool GetExtraDescriptor(const std::string& id,
|
| - InputMethodDescriptor* descriptor) {
|
| - std::map<std::string, InputMethodDescriptor>::const_iterator ix =
|
| - extra_input_method_ids_.find(id);
|
| - if (ix != extra_input_method_ids_.end()) {
|
| - *descriptor = ix->second;
|
| - return true;
|
| - } else {
|
| - return false;
|
| - }
|
| - }
|
| -
|
| - virtual InputMethodDescriptor GetPreviousInputMethod() const {
|
| - if (previous_input_method_.id().empty()) {
|
| - return InputMethodDescriptor::GetFallbackInputMethodDescriptor();
|
| - }
|
| - return previous_input_method_;
|
| - }
|
| -
|
| - virtual InputMethodDescriptor GetCurrentInputMethod() const {
|
| - if (current_input_method_.id().empty()) {
|
| - return InputMethodDescriptor::GetFallbackInputMethodDescriptor();
|
| - }
|
| - return current_input_method_;
|
| - }
|
| -
|
| - virtual InputMethodPropertyList GetCurrentInputMethodProperties() const {
|
| - if (should_hide_properties_ ||
|
| - InputMethodUtil::IsKeyboardLayout(GetCurrentInputMethod().id())) {
|
| - return InputMethodPropertyList();
|
| - }
|
| - return current_ime_properties_;
|
| - }
|
| -
|
| - virtual void SendHandwritingStroke(const HandwritingStroke& stroke) {
|
| - ibus_controller_->SendHandwritingStroke(stroke);
|
| - }
|
| -
|
| - virtual void CancelHandwritingStrokes(int stroke_count) {
|
| - // TODO(yusukes): Rename the function to CancelHandwritingStrokes.
|
| - ibus_controller_->CancelHandwriting(stroke_count);
|
| - }
|
| -
|
| - virtual void RegisterVirtualKeyboard(const GURL& launch_url,
|
| - const std::string& name,
|
| - const std::set<std::string>& layouts,
|
| - bool is_system) {
|
| - virtual_keyboard_selector_.AddVirtualKeyboard(launch_url,
|
| - name,
|
| - layouts,
|
| - is_system);
|
| - }
|
| -
|
| - virtual const std::map<GURL, const VirtualKeyboard*>&
|
| - GetUrlToKeyboardMapping() const {
|
| - return virtual_keyboard_selector_.url_to_keyboard();
|
| - }
|
| -
|
| - virtual const std::multimap<std::string, const VirtualKeyboard*>&
|
| - GetLayoutNameToKeyboardMapping() const {
|
| - return virtual_keyboard_selector_.layout_to_keyboard();
|
| - }
|
| -
|
| - virtual bool SetVirtualKeyboardPreference(const std::string& input_method_id,
|
| - const GURL& extention_url) {
|
| - const bool result = virtual_keyboard_selector_.SetUserPreference(
|
| - input_method_id, extention_url);
|
| - UpdateVirtualKeyboardUI();
|
| - return result;
|
| - }
|
| -
|
| - virtual void ClearAllVirtualKeyboardPreferences() {
|
| - virtual_keyboard_selector_.ClearAllUserPreferences();
|
| - UpdateVirtualKeyboardUI();
|
| - }
|
| -
|
| - virtual InputMethodUtil* GetInputMethodUtil() {
|
| - return &util_;
|
| - }
|
| -
|
| - virtual XKeyboard* GetXKeyboard() {
|
| - return xkeyboard_.get();
|
| - }
|
| -
|
| - virtual void CandidateWindowOpened() {
|
| - FOR_EACH_OBSERVER(InputMethodManager::CandidateWindowObserver,
|
| - candidate_window_observers_,
|
| - CandidateWindowOpened(this));
|
| - }
|
| -
|
| - virtual void CandidateWindowClosed() {
|
| - FOR_EACH_OBSERVER(InputMethodManager::CandidateWindowObserver,
|
| - candidate_window_observers_,
|
| - CandidateWindowClosed(this));
|
| - }
|
| -
|
| - virtual bool SwitchToNextInputMethod() {
|
| - if (ignore_hotkeys_) {
|
| - return false;
|
| - }
|
| -
|
| - // Sanity checks.
|
| - if (active_input_method_ids_.empty()) {
|
| - LOG(ERROR) << "active input method is empty";
|
| - return false;
|
| - }
|
| - if (current_input_method_.id().empty()) {
|
| - LOG(ERROR) << "current_input_method_ is unknown";
|
| - return false;
|
| - }
|
| -
|
| - // Find the next input method.
|
| - std::vector<std::string>::const_iterator iter =
|
| - std::find(active_input_method_ids_.begin(),
|
| - active_input_method_ids_.end(),
|
| - current_input_method_.id());
|
| - if (iter != active_input_method_ids_.end()) {
|
| - ++iter;
|
| - }
|
| - if (iter == active_input_method_ids_.end()) {
|
| - iter = active_input_method_ids_.begin();
|
| - }
|
| - ChangeInputMethod(*iter);
|
| - return true;
|
| - }
|
| -
|
| - virtual bool SwitchToPreviousInputMethod() {
|
| - if (ignore_hotkeys_) {
|
| - return false;
|
| - }
|
| -
|
| - // Sanity check.
|
| - if (active_input_method_ids_.empty()) {
|
| - LOG(ERROR) << "active input method is empty";
|
| - return false;
|
| - }
|
| -
|
| - 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.
|
| - return SwitchToNextInputMethod();
|
| - }
|
| - ChangeInputMethod(*iter);
|
| - return true;
|
| - }
|
| -
|
| - virtual bool SwitchInputMethod(const ui::Accelerator& accelerator) {
|
| - if (ignore_hotkeys_) {
|
| - return false;
|
| - }
|
| -
|
| - // Sanity check.
|
| - if (active_input_method_ids_.empty()) {
|
| - LOG(ERROR) << "active input method is empty";
|
| - return false;
|
| - }
|
| -
|
| - // Get the list of input method ids for the |accelerator|. For example, get
|
| - // { "mozc-hangul", "xkb:kr:kr104:kor" } for ui::VKEY_DBE_SBCSCHAR.
|
| - std::vector<std::string> input_method_ids_to_switch;
|
| - switch (accelerator.key_code()) {
|
| - case ui::VKEY_CONVERT: // Henkan key on JP106 keyboard
|
| - input_method_ids_to_switch.push_back("mozc-jp");
|
| - break;
|
| - case ui::VKEY_NONCONVERT: // Muhenkan key on JP106 keyboard
|
| - input_method_ids_to_switch.push_back("xkb:jp::jpn");
|
| - break;
|
| - case ui::VKEY_DBE_SBCSCHAR: // ZenkakuHankaku key on JP106 keyboard
|
| - case ui::VKEY_DBE_DBCSCHAR:
|
| - input_method_ids_to_switch.push_back("mozc-jp");
|
| - input_method_ids_to_switch.push_back("xkb:jp::jpn");
|
| - break;
|
| - case ui::VKEY_HANGUL: // Hangul (or right Alt) key on Korean keyboard
|
| - case ui::VKEY_SPACE: // Shift+Space
|
| - input_method_ids_to_switch.push_back("mozc-hangul");
|
| - input_method_ids_to_switch.push_back("xkb:kr:kr104:kor");
|
| - break;
|
| - default:
|
| - NOTREACHED();
|
| - break;
|
| - }
|
| - if (input_method_ids_to_switch.empty()) {
|
| - LOG(ERROR) << "Unexpected VKEY: " << accelerator.key_code();
|
| - return false;
|
| - }
|
| -
|
| - // Obtain the intersection of input_method_ids_to_switch and
|
| - // 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 (std::find(active_input_method_ids_.begin(),
|
| - active_input_method_ids_.end(),
|
| - id) != active_input_method_ids_.end()) {
|
| - ids.push_back(id);
|
| - }
|
| - }
|
| - if (ids.empty()) {
|
| - // No input method for the accelerator is active. For example, we should
|
| - // just ignore VKEY_HANGUL when mozc-hangul is not active.
|
| - return false;
|
| - }
|
| -
|
| - // If |current_input_method_| is not in ids, switch to ids[0]. If
|
| - // |current_input_method_| is ids[N], switch to ids[N+1].
|
| - std::vector<std::string>::const_iterator iter =
|
| - std::find(ids.begin(), ids.end(), current_input_method_.id());
|
| - if (iter != ids.end()) {
|
| - ++iter;
|
| - }
|
| - if (iter == ids.end()) {
|
| - iter = ids.begin();
|
| - }
|
| - ChangeInputMethod(*iter);
|
| - return true; // consume the accelerator.
|
| - }
|
| -
|
| - virtual void EnableHotkeys() {
|
| - ignore_hotkeys_ = false;
|
| - }
|
| -
|
| - virtual void DisableHotkeys() {
|
| - ignore_hotkeys_ = true;
|
| - }
|
| -
|
| - static InputMethodManagerImpl* GetInstance() {
|
| - return Singleton<InputMethodManagerImpl,
|
| - DefaultSingletonTraits<InputMethodManagerImpl> >::get();
|
| - }
|
| -
|
| - private:
|
| - friend struct DefaultSingletonTraits<InputMethodManagerImpl>;
|
| -
|
| - // Returns true if the given input method config value is a string list
|
| - // that only contains an input method ID of a keyboard layout.
|
| - bool ContainOnlyKeyboardLayout(const std::vector<std::string>& value) {
|
| - for (size_t i = 0; i < value.size(); ++i) {
|
| - if (!InputMethodUtil::IsKeyboardLayout(value[i])) {
|
| - return false;
|
| - }
|
| - }
|
| - return true;
|
| - }
|
| -
|
| - // Starts input method daemon based on the input method configuration being
|
| - // updated. |section| is a section name of the input method configuration
|
| - // (e.g. "general", "general/hotkey"). |config_name| is a name of the
|
| - // configuration (e.g. "preload_engines", "previous_engine"). |value| is the
|
| - // configuration value to be set.
|
| - void MaybeStartInputMethodDaemon(const std::string& section,
|
| - const std::string& config_name,
|
| - const InputMethodConfigValue& value) {
|
| - if (section == language_prefs::kGeneralSectionName &&
|
| - config_name == language_prefs::kPreloadEnginesConfigName &&
|
| - value.type == InputMethodConfigValue::kValueTypeStringList &&
|
| - !value.string_list_value.empty()) {
|
| - // If there is only one input method which is a keyboard layout,
|
| - // we don't start the input method processes.
|
| - if (ContainOnlyKeyboardLayout(value.string_list_value)) {
|
| - // Do not start the input method daemon.
|
| - return;
|
| - }
|
| -
|
| - // Otherwise, start the input method daemon.
|
| - const bool just_started = StartInputMethodDaemon();
|
| - if (!just_started) {
|
| - // The daemon is already running.
|
| - // Do not |update tentative_current_input_method_id_|.
|
| - return;
|
| - }
|
| -
|
| - // The daemon has just been started. To select the initial input method
|
| - // engine correctly, update |tentative_current_input_method_id_|.
|
| - if (tentative_current_input_method_id_.empty()) {
|
| - // Since the |current_input_method_| is in the preloaded engine list,
|
| - // switch to the engine. This is necessary ex. for the following case:
|
| - // 1. "xkb:jp::jpn" is enabled. ibus-daemon is not running.
|
| - // 2. A user enabled "mozc" via DOMUI as well. ibus-daemon is started
|
| - // and the preloaded engine list is set to "mozc,xkb:jp::jpn".
|
| - // 3. ibus-daemon selects "mozc" as its current engine since "mozc" is
|
| - // on top of the preloaded engine list.
|
| - // 4. Therefore, we have to change the current engine to "xkb:jp::jpn"
|
| - // explicitly to avoid unexpected engine switch.
|
| - tentative_current_input_method_id_ = current_input_method_.id();
|
| - }
|
| -
|
| - if (std::find(value.string_list_value.begin(),
|
| - value.string_list_value.end(),
|
| - tentative_current_input_method_id_)
|
| - == value.string_list_value.end()) {
|
| - // The |current_input_method_| is NOT in the preloaded engine list.
|
| - // In this case, ibus-daemon will automatically select the first engine
|
| - // in the list, |value.string_list_value[0]|, and send global engine
|
| - // changed signal to Chrome. See crosbug.com/13406.
|
| - tentative_current_input_method_id_.clear();
|
| - }
|
| - }
|
| - }
|
| -
|
| - // Stops input method daemon based on the |enable_auto_ime_shutdown_| flag
|
| - // and input method configuration being updated.
|
| - // See also: MaybeStartInputMethodDaemon().
|
| - void MaybeStopInputMethodDaemon() {
|
| - // If there is only one input method which is a keyboard layout,
|
| - // and |enable_auto_ime_shutdown_| is true, we'll stop the input
|
| - // method daemon.
|
| - if (ContainOnlyKeyboardLayout(active_input_method_ids_) &&
|
| - enable_auto_ime_shutdown_) {
|
| - if (StopInputMethodDaemon()) {
|
| - // The process is killed. Change the current keyboard layout.
|
| - // We shouldn't use SetCurrentKeyboardLayoutByName() here. See
|
| - // comments at ChangeCurrentInputMethod() for details.
|
| - ChangeCurrentInputMethodFromId(active_input_method_ids_[0]);
|
| - }
|
| - }
|
| - }
|
| -
|
| - // Change the keyboard layout per input method configuration being
|
| - // updated, if necessary. See also: MaybeStartInputMethodDaemon().
|
| - void MaybeChangeCurrentKeyboardLayout(const std::string& section,
|
| - const std::string& config_name,
|
| - const InputMethodConfigValue& value) {
|
| - if (section == language_prefs::kGeneralSectionName &&
|
| - config_name == language_prefs::kPreloadEnginesConfigName) {
|
| - if (value.string_list_value.size() == 1 ||
|
| - (value.string_list_value.size() != 0 &&
|
| - std::find(value.string_list_value.begin(),
|
| - value.string_list_value.end(),
|
| - current_input_method_.id()) ==
|
| - value.string_list_value.end())) {
|
| - // This is necessary to initialize current_input_method_. This is also
|
| - // necessary when the current layout (e.g. INTL) out of two or more
|
| - // active ones (e.g. US, DV, and INTL) is disabled.
|
| - ChangeCurrentInputMethodFromId(value.string_list_value[0]);
|
| - }
|
| - DCHECK(!current_input_method_.id().empty());
|
| -
|
| - // Update the indicator.
|
| - // TODO(yusukes): Remove ActiveInputMethodsChanged notification in
|
| - // FlushImeConfig().
|
| - const size_t num_active_input_methods = GetNumActiveInputMethods();
|
| - FOR_EACH_OBSERVER(InputMethodManager::Observer, observers_,
|
| - ActiveInputMethodsChanged(this,
|
| - GetCurrentInputMethod(),
|
| - num_active_input_methods));
|
| - }
|
| - }
|
| -
|
| - // Changes the current input method to |input_method_id| via IBus
|
| - // daemon. If the id is not in the preload_engine list, this function
|
| - // changes the current method to the first preloaded engine. Returns
|
| - // true if the current engine is switched to |input_method_id| or the
|
| - // first one.
|
| - bool ChangeInputMethodViaIBus(const std::string& input_method_id) {
|
| - std::string input_method_id_to_switch = input_method_id;
|
| -
|
| - if (!InputMethodIsActivated(input_method_id)) {
|
| - // This path might be taken if prefs::kLanguageCurrentInputMethod (NOT
|
| - // synced with cloud) and kLanguagePreloadEngines (synced with cloud) are
|
| - // mismatched. e.g. the former is 'xkb:us::eng' and the latter (on the
|
| - // sync server) is 'xkb:jp::jpn,mozc'.
|
| - scoped_ptr<InputMethodDescriptors> input_methods(GetActiveInputMethods());
|
| - DCHECK(!input_methods->empty());
|
| - if (!input_methods->empty()) {
|
| - input_method_id_to_switch = input_methods->at(0).id();
|
| - LOG(INFO) << "Can't change the current input method to "
|
| - << input_method_id << " since the engine is not preloaded. "
|
| - << "Switch to " << input_method_id_to_switch << " instead.";
|
| - }
|
| - }
|
| -
|
| - if (ibus_controller_->ChangeInputMethod(input_method_id_to_switch)) {
|
| - return true;
|
| - }
|
| -
|
| - // ChangeInputMethod() fails if the IBus daemon is not yet ready.
|
| - LOG(ERROR) << "Can't switch input method to " << input_method_id_to_switch;
|
| - return false;
|
| - }
|
| -
|
| - // Flushes the input method config data. The config data is queued up in
|
| - // |pending_config_requests_| until the config backend (ibus-memconf)
|
| - // starts.
|
| - void FlushImeConfig() {
|
| - bool active_input_methods_are_changed = false;
|
| - InputMethodConfigRequests::iterator iter = pending_config_requests_.begin();
|
| - while (iter != pending_config_requests_.end()) {
|
| - const std::string& section = iter->first.first;
|
| - const std::string& config_name = iter->first.second;
|
| - InputMethodConfigValue& value = iter->second;
|
| -
|
| - if (config_name == language_prefs::kPreloadEnginesConfigName &&
|
| - !tentative_current_input_method_id_.empty()) {
|
| - // We should use |tentative_current_input_method_id_| as the initial
|
| - // active input method for the following reasons:
|
| - //
|
| - // 1) Calls to ChangeInputMethod() will fail if the input method has not
|
| - // yet been added to preload_engines. As such, the call is deferred
|
| - // until after all config values have been sent to the IME process.
|
| - //
|
| - // 2) We might have already changed the current input method to one
|
| - // of XKB layouts without going through the IBus daemon (we can do
|
| - // it without the IBus daemon started).
|
| - std::vector<std::string>::iterator engine_iter = std::find(
|
| - value.string_list_value.begin(),
|
| - value.string_list_value.end(),
|
| - tentative_current_input_method_id_);
|
| - if (engine_iter != value.string_list_value.end()) {
|
| - // Use std::rotate to keep the relative order of engines the same e.g.
|
| - // from "A,B,C" to "C,A,B".
|
| - // We don't have to |active_input_method_ids_|, which decides the
|
| - // order of engines in the switcher menu, since the relative order
|
| - // of |value.string_list_value| is not changed.
|
| - std::rotate(value.string_list_value.begin(),
|
| - engine_iter, // this becomes the new first element
|
| - value.string_list_value.end());
|
| -#if defined(HAVE_IBUS)
|
| -#if IBUS_CHECK_VERSION(1, 4, 99)
|
| - ibus_controller_->ChangeInputMethod(value.string_list_value[0]);
|
| -#endif
|
| -#endif
|
| - } else {
|
| - LOG(WARNING) << tentative_current_input_method_id_
|
| - << " is not in preload_engines: " << value.ToString();
|
| - }
|
| - tentative_current_input_method_id_.erase();
|
| - }
|
| -
|
| - if (ibus_controller_->SetInputMethodConfig(section, config_name, value)) {
|
| - // Check if it's a change in active input methods.
|
| - if (config_name == language_prefs::kPreloadEnginesConfigName) {
|
| - active_input_methods_are_changed = true;
|
| - VLOG(1) << "Updated preload_engines: " << value.ToString();
|
| - }
|
| - // Successfully sent. Remove the command and proceed to the next one.
|
| - pending_config_requests_.erase(iter++);
|
| - } else {
|
| - // If SetInputMethodConfig() fails, subsequent calls will likely fail.
|
| - break;
|
| - }
|
| - }
|
| -
|
| - // Notify the current input method and the number of active input methods to
|
| - // the UI so that the UI could determine e.g. if it should show/hide the
|
| - // input method indicator, etc. We have to call FOR_EACH_OBSERVER here since
|
| - // updating "preload_engine" does not necessarily trigger a DBus signal such
|
| - // as "global-engine-changed". For example,
|
| - // 1) If we change the preload_engine from "xkb:us:intl:eng" (i.e. the
|
| - // indicator is hidden) to "xkb:us:intl:eng,mozc", we have to update UI
|
| - // so it shows the indicator, but no signal is sent from ibus-daemon
|
| - // because the current input method is not changed.
|
| - // 2) If we change the preload_engine from "xkb:us::eng,mozc" (i.e. the
|
| - // indicator is shown and ibus-daemon is started) to "xkb:us::eng", we
|
| - // have to update UI so it hides the indicator, but we should not expect
|
| - // that ibus-daemon could send a DBus signal since the daemon is killed
|
| - // right after this FlushImeConfig() call.
|
| - if (active_input_methods_are_changed) {
|
| - // The |current_input_method_| member might be stale here as
|
| - // SetInputMethodConfig("preload_engine") call above might change the
|
| - // current input method in ibus-daemon (ex. this occurs when the
|
| - // input method currently in use is removed from the options
|
| - // page). However, it should be safe to use the member here,
|
| - // for the following reasons:
|
| - // 1. If ibus-daemon is to be killed, we'll switch to the only one
|
| - // keyboard layout, and observers are notified. See
|
| - // MaybeStopInputMethodDaemon() for details.
|
| - // 2. Otherwise, "global-engine-changed" signal is delivered from
|
| - // ibus-daemon, and observers are notified. See
|
| - // InputMethodChangedHandler() for details.
|
| - const size_t num_active_input_methods = GetNumActiveInputMethods();
|
| - FOR_EACH_OBSERVER(InputMethodManager::Observer, observers_,
|
| - ActiveInputMethodsChanged(this,
|
| - current_input_method_,
|
| - num_active_input_methods));
|
| - }
|
| - }
|
| -
|
| - // IBusController override.
|
| - virtual void OnCurrentInputMethodChanged(
|
| - const InputMethodDescriptor& current_input_method) {
|
| - // The handler is called when the input method method change is
|
| - // notified via a DBus connection. Since the DBus notificatiosn are
|
| - // handled in the UI thread, we can assume that this function always
|
| - // runs on the UI thread, but just in case.
|
| - if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
|
| - LOG(ERROR) << "Not on UI thread";
|
| - return;
|
| - }
|
| -
|
| - ChangeCurrentInputMethod(current_input_method);
|
| - }
|
| -
|
| - // IBusController override.
|
| - virtual void OnRegisterImeProperties(
|
| - const InputMethodPropertyList& prop_list) {
|
| - // See comments in InputMethodChangedHandler.
|
| - if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
|
| - LOG(ERROR) << "Not on UI thread";
|
| - return;
|
| - }
|
| -
|
| - RegisterProperties(prop_list);
|
| - }
|
| -
|
| - // IBusController override.
|
| - virtual void OnUpdateImeProperty(
|
| - const InputMethodPropertyList& prop_list) {
|
| - // See comments in InputMethodChangedHandler.
|
| - if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
|
| - LOG(ERROR) << "Not on UI thread";
|
| - return;
|
| - }
|
| -
|
| - UpdateProperty(prop_list);
|
| - }
|
| -
|
| - // IBusController override.
|
| - virtual void OnConnectionChange(bool connected) {
|
| - // See comments in InputMethodChangedHandler.
|
| - if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
|
| - LOG(ERROR) << "Not on UI thread";
|
| - return;
|
| - }
|
| -
|
| - ime_connected_ = connected;
|
| - if (connected) {
|
| - pending_config_requests_.clear();
|
| - pending_config_requests_.insert(current_config_values_.begin(),
|
| - current_config_values_.end());
|
| - FlushImeConfig();
|
| - }
|
| - }
|
| -
|
| - // Changes the current input method from the given input method
|
| - // descriptor. This function updates states like current_input_method_
|
| - // and notifies observers about the change (that will update the
|
| - // preferences), hence this function should always be used even if you
|
| - // just need to change the current keyboard layout.
|
| - void ChangeCurrentInputMethod(const InputMethodDescriptor& new_input_method) {
|
| - if (current_input_method_.id() != new_input_method.id()) {
|
| - previous_input_method_ = current_input_method_;
|
| - current_input_method_ = new_input_method;
|
| -
|
| - // Change the keyboard layout to a preferred layout for the input method.
|
| - if (!xkeyboard_->SetCurrentKeyboardLayoutByName(
|
| - current_input_method_.keyboard_layout())) {
|
| - LOG(ERROR) << "Failed to change keyboard layout to "
|
| - << current_input_method_.keyboard_layout();
|
| - }
|
| - }
|
| -
|
| - // Update input method indicators (e.g. "US", "DV") in Chrome windows.
|
| - // For now, we have to do this every time to keep indicators updated. See
|
| - // comments near the FOR_EACH_OBSERVER call in FlushImeConfig() for details.
|
| - const size_t num_active_input_methods = GetNumActiveInputMethods();
|
| - FOR_EACH_OBSERVER(InputMethodManager::Observer, observers_,
|
| - InputMethodChanged(this,
|
| - current_input_method_,
|
| - num_active_input_methods));
|
| -
|
| - UpdateVirtualKeyboardUI();
|
| - }
|
| -
|
| - void UpdateVirtualKeyboardUI() {
|
| -#if defined(USE_VIRTUAL_KEYBOARD)
|
| - const VirtualKeyboard* virtual_keyboard = NULL;
|
| - std::string virtual_keyboard_layout = "";
|
| -
|
| - const std::vector<std::string>& layouts_vector =
|
| - current_input_method_.virtual_keyboard_layouts();
|
| - std::vector<std::string>::const_iterator iter;
|
| - for (iter = layouts_vector.begin(); iter != layouts_vector.end(); ++iter) {
|
| - virtual_keyboard =
|
| - virtual_keyboard_selector_.SelectVirtualKeyboard(*iter);
|
| - if (virtual_keyboard) {
|
| - virtual_keyboard_layout = *iter;
|
| - break;
|
| - }
|
| - }
|
| -
|
| - if (!virtual_keyboard) {
|
| - // The system virtual keyboard does not support some XKB layouts? or
|
| - // a third-party input method engine uses a wrong virtual keyboard
|
| - // layout name? Fallback to the default layout.
|
| - LOG(ERROR) << "Could not find a virtual keyboard for "
|
| - << current_input_method_.id();
|
| -
|
| - // If the hardware is for US, show US Qwerty virtual keyboard.
|
| - // If it's for France, show Azerty one.
|
| - const std::string fallback_id = GetInputMethodUtil()->
|
| - GetHardwareInputMethodId();
|
| - const InputMethodDescriptor* fallback_desc =
|
| - GetInputMethodUtil()->GetInputMethodDescriptorFromId(fallback_id);
|
| -
|
| - DCHECK(fallback_desc);
|
| - const std::vector<std::string>& fallback_layouts_vector =
|
| - fallback_desc->virtual_keyboard_layouts();
|
| -
|
| - for (iter = fallback_layouts_vector.begin();
|
| - iter != fallback_layouts_vector.end();
|
| - ++iter) {
|
| - virtual_keyboard =
|
| - virtual_keyboard_selector_.SelectVirtualKeyboard(*iter);
|
| - if (virtual_keyboard) {
|
| - virtual_keyboard_layout = *iter;
|
| - LOG(ERROR) << "Fall back to '" << (*iter) << "' virtual keyboard";
|
| - break;
|
| - }
|
| - }
|
| - }
|
| -
|
| - if (!virtual_keyboard) {
|
| - // kFallbackVirtualKeyboardLayout should always be supported by one of the
|
| - // system virtual keyboards.
|
| - static const char kFallbackVirtualKeyboardLayout[] = "us";
|
| -
|
| - LOG(ERROR) << "Could not find a FALLBACK virtual keyboard for "
|
| - << current_input_method_.id()
|
| - << ". Use '" << kFallbackVirtualKeyboardLayout
|
| - << "' virtual keyboard";
|
| - virtual_keyboard = virtual_keyboard_selector_.SelectVirtualKeyboard(
|
| - kFallbackVirtualKeyboardLayout);
|
| - virtual_keyboard_layout = kFallbackVirtualKeyboardLayout;
|
| - }
|
| -
|
| - if (virtual_keyboard) {
|
| - FOR_EACH_OBSERVER(VirtualKeyboardObserver, virtual_keyboard_observers_,
|
| - VirtualKeyboardChanged(this,
|
| - *virtual_keyboard,
|
| - virtual_keyboard_layout));
|
| - }
|
| -#endif // USE_VIRTUAL_KEYBOARD
|
| - }
|
| -
|
| - // Changes the current input method from the given input method ID.
|
| - // This function is just a wrapper of ChangeCurrentInputMethod().
|
| - void ChangeCurrentInputMethodFromId(const std::string& input_method_id) {
|
| - const InputMethodDescriptor* descriptor =
|
| - util_.GetInputMethodDescriptorFromId(input_method_id);
|
| - if (descriptor) {
|
| - ChangeCurrentInputMethod(*descriptor);
|
| - } else {
|
| - LOG(ERROR) << "Descriptor is not found for: " << input_method_id;
|
| - }
|
| - }
|
| -
|
| - // Registers the properties used by the current input method.
|
| - void RegisterProperties(const InputMethodPropertyList& prop_list) {
|
| - // |prop_list| might be empty. This means "hide properties."
|
| - if (prop_list.empty()) {
|
| - should_hide_properties_ = true;
|
| - } else {
|
| - should_hide_properties_ = false;
|
| - current_ime_properties_ = prop_list;
|
| - }
|
| - // Update input method menu
|
| - FOR_EACH_OBSERVER(InputMethodManager::Observer, observers_,
|
| - PropertyListChanged(this,
|
| - GetCurrentInputMethodProperties()));
|
| - }
|
| -
|
| - // Starts the input method daemon. Unlike MaybeStopInputMethodDaemon(),
|
| - // this function always starts the daemon. Returns true if the daemon is
|
| - // started. Otherwise, e.g. the daemon is already started, returns false.
|
| - bool StartInputMethodDaemon() {
|
| - should_launch_ime_ = true;
|
| - return MaybeLaunchInputMethodDaemon();
|
| - }
|
| -
|
| - // Updates the properties used by the current input method.
|
| - void UpdateProperty(const InputMethodPropertyList& prop_list) {
|
| - for (size_t i = 0; i < prop_list.size(); ++i) {
|
| - FindAndUpdateProperty(prop_list[i], ¤t_ime_properties_);
|
| - }
|
| -
|
| - // Update input method menu
|
| - FOR_EACH_OBSERVER(InputMethodManager::Observer, observers_,
|
| - PropertyListChanged(this,
|
| - GetCurrentInputMethodProperties()));
|
| - }
|
| -
|
| - // Launches an input method procsess specified by the given command
|
| - // line. On success, returns true and stores the process handle in
|
| - // |process_handle|. Otherwise, returns false, and the contents of
|
| - // |process_handle| is untouched. OnImeShutdown will be called when the
|
| - // process terminates.
|
| - bool LaunchInputMethodProcess(const std::string& command_line,
|
| - base::ProcessHandle* process_handle) {
|
| - std::vector<std::string> argv;
|
| - base::ProcessHandle handle = base::kNullProcessHandle;
|
| -
|
| - // TODO(zork): export "LD_PRELOAD=/usr/lib/libcrash.so"
|
| - base::SplitString(command_line, ' ', &argv);
|
| -
|
| - if (!base::LaunchProcess(argv, base::LaunchOptions(), &handle)) {
|
| - LOG(ERROR) << "Could not launch: " << command_line;
|
| - return false;
|
| - }
|
| -
|
| - // g_child_watch_add is necessary to prevent the process from becoming a
|
| - // zombie.
|
| - // TODO(yusukes): port g_child_watch_add to base/process_utils_posix.cc.
|
| - const base::ProcessId pid = base::GetProcId(handle);
|
| - g_child_watch_add(pid,
|
| - reinterpret_cast<GChildWatchFunc>(OnImeShutdown),
|
| - this);
|
| -
|
| - *process_handle = handle;
|
| - VLOG(1) << command_line << " (PID=" << pid << ") is started";
|
| - return true;
|
| - }
|
| -
|
| - // Launches input method daemon if these are not yet running. Returns true if
|
| - // the daemon is started. Otherwise, e.g. the daemon is already started,
|
| - // returns false.
|
| - bool MaybeLaunchInputMethodDaemon() {
|
| - if (!should_launch_ime_) {
|
| - return false;
|
| - }
|
| -
|
| - if (shutting_down_) {
|
| - NOTREACHED() << "Trying to launch input method while shutting down";
|
| - return false;
|
| - }
|
| -
|
| -#if !defined(USE_VIRTUAL_KEYBOARD)
|
| - if (!candidate_window_controller_.get()) {
|
| - candidate_window_controller_.reset(
|
| - CandidateWindowController::CreateCandidateWindowController());
|
| - if (candidate_window_controller_->Init()) {
|
| - candidate_window_controller_->AddObserver(this);
|
| - } else {
|
| - LOG(WARNING) << "Failed to initialize the candidate window controller";
|
| - }
|
| - }
|
| -#endif
|
| -
|
| - if (ibus_daemon_process_handle_ != base::kNullProcessHandle) {
|
| - return false; // ibus-daemon is already running.
|
| - }
|
| -
|
| - // TODO(zork): Send output to /var/log/ibus.log
|
| - const std::string ibus_daemon_command_line =
|
| - base::StringPrintf(
|
| - "%s --panel=disable --cache=none --restart --replace",
|
| - kIBusDaemonPath);
|
| - if (!LaunchInputMethodProcess(
|
| - ibus_daemon_command_line, &ibus_daemon_process_handle_)) {
|
| - LOG(ERROR) << "Failed to launch " << ibus_daemon_command_line;
|
| - return false;
|
| - }
|
| - return true;
|
| - }
|
| -
|
| - // Called when the input method process is shut down.
|
| - static void OnImeShutdown(GPid pid,
|
| - gint status,
|
| - InputMethodManagerImpl* library) {
|
| - if (library->ibus_daemon_process_handle_ != base::kNullProcessHandle &&
|
| - base::GetProcId(library->ibus_daemon_process_handle_) == pid) {
|
| - library->ibus_daemon_process_handle_ = base::kNullProcessHandle;
|
| - }
|
| -
|
| - // Restart input method daemon if needed.
|
| - library->MaybeLaunchInputMethodDaemon();
|
| - }
|
| -
|
| - // Stops the backend input method daemon. This function should also be
|
| - // called from MaybeStopInputMethodDaemon(), except one case where we
|
| - // stop the input method daemon at Chrome shutdown in Observe(). Returns true
|
| - // if the daemon is stopped. Otherwise, e.g. the daemon is already stopped,
|
| - // returns false.
|
| - bool StopInputMethodDaemon() {
|
| - should_launch_ime_ = false;
|
| - if (ibus_daemon_process_handle_ != base::kNullProcessHandle) {
|
| - const base::ProcessId pid = base::GetProcId(ibus_daemon_process_handle_);
|
| - if (!ibus_controller_->StopInputMethodProcess()) {
|
| - LOG(ERROR) << "StopInputMethodProcess IPC failed. Sending SIGTERM to "
|
| - << "PID " << pid;
|
| - base::KillProcess(ibus_daemon_process_handle_, -1, false /* wait */);
|
| - }
|
| - VLOG(1) << "ibus-daemon (PID=" << pid << ") is terminated";
|
| - ibus_daemon_process_handle_ = base::kNullProcessHandle;
|
| - return true;
|
| - }
|
| - return false;
|
| - }
|
| -
|
| - void SetEnableAutoImeShutdown(bool enable) {
|
| - // TODO(yusukes): this is a workaround for crosbug.com/27051. Uncommen this
|
| - // when the bug is fixed.
|
| -
|
| - // enable_auto_ime_shutdown_ = enable;
|
| - }
|
| -
|
| - void SetEnableExtensionIMEs(bool enable) {
|
| - enable_extension_imes_ = enable;
|
| - }
|
| -
|
| - // content::NotificationObserver implementation:
|
| - void Observe(int type,
|
| - const content::NotificationSource& source,
|
| - const content::NotificationDetails& details) {
|
| - // Stop the input method daemon on browser shutdown.
|
| - if (type == content::NOTIFICATION_APP_TERMINATING) {
|
| - shutting_down_ = true;
|
| - notification_registrar_.RemoveAll();
|
| - StopInputMethodDaemon();
|
| -#if !defined(USE_VIRTUAL_KEYBOARD)
|
| - if (candidate_window_controller_.get())
|
| - candidate_window_controller_->RemoveObserver(this);
|
| - candidate_window_controller_.reset(NULL);
|
| -#endif
|
| - // |browser_state_monitor_| has to be destructed while the PrefService
|
| - // object associated with the monitor is alive. (crbug.com/120183)
|
| - browser_state_monitor_.reset();
|
| - }
|
| - }
|
| -
|
| - // The IBus controller is used to control the input method status and
|
| - // allow allow callbacks when the input method status changes.
|
| - scoped_ptr<IBusController> ibus_controller_;
|
| - ObserverList<InputMethodManager::Observer> observers_;
|
| - ObserverList<InputMethodManager::CandidateWindowObserver>
|
| - candidate_window_observers_;
|
| - ObserverList<VirtualKeyboardObserver> virtual_keyboard_observers_;
|
| -
|
| - // The input method which was/is selected.
|
| - InputMethodDescriptor previous_input_method_;
|
| - InputMethodDescriptor current_input_method_;
|
| -
|
| - // The input method properties which the current input method uses. The list
|
| - // might be empty when no input method is used.
|
| - InputMethodPropertyList current_ime_properties_;
|
| - bool should_hide_properties_;
|
| -
|
| - typedef std::pair<std::string, std::string> ConfigKeyType;
|
| - typedef std::map<
|
| - ConfigKeyType, InputMethodConfigValue> InputMethodConfigRequests;
|
| - // SetInputMethodConfig requests that are not yet completed.
|
| - // Use a map to queue config requests, so we only send the last request for
|
| - // the same config key (i.e. we'll discard ealier requests for the same
|
| - // config key). As we discard old requests for the same config key, the order
|
| - // of requests doesn't matter, so it's safe to use a map.
|
| - InputMethodConfigRequests pending_config_requests_;
|
| -
|
| - // Values that have been set via SetInputMethodConfig(). We keep a copy
|
| - // available to resend if the ime restarts and loses its state.
|
| - InputMethodConfigRequests current_config_values_;
|
| -
|
| - // This is used to register this object to APP_TERMINATING notification.
|
| - content::NotificationRegistrar notification_registrar_;
|
| -
|
| - // True if we should launch the input method daemon.
|
| - bool should_launch_ime_;
|
| - // True if the connection to the IBus daemon is alive.
|
| - bool ime_connected_;
|
| - // True if we should stop input method daemon when there are no input
|
| - // methods other than one for the hardware keyboard.
|
| - bool enable_auto_ime_shutdown_;
|
| - // True if extension IMEs can be enabled.
|
| - bool enable_extension_imes_;
|
| - // The ID of the tentative current input method (ex. "mozc"). This value
|
| - // can be different from the actual current input method, if
|
| - // ChangeInputMethod() fails.
|
| - // TODO(yusukes): clear this variable when a user logs in.
|
| - std::string tentative_current_input_method_id_;
|
| -
|
| - // The candidate window. This will be deleted when the APP_TERMINATING
|
| - // message is sent.
|
| -#if !defined(USE_VIRTUAL_KEYBOARD)
|
| - scoped_ptr<CandidateWindowController> candidate_window_controller_;
|
| -#endif
|
| -
|
| - // True if we've received the APP_TERMINATING notification.
|
| - bool shutting_down_;
|
| -
|
| - // The process handle of the IBus daemon. kNullProcessHandle if it's not
|
| - // running.
|
| - base::ProcessHandle ibus_daemon_process_handle_;
|
| -
|
| - // An object which keeps a list of available virtual keyboards.
|
| - VirtualKeyboardSelector virtual_keyboard_selector_;
|
| -
|
| - // The active input method ids cache.
|
| - std::vector<std::string> active_input_method_ids_;
|
| -
|
| - // Extra input methods that have been explicitly added to the menu, such as
|
| - // those created by extension.
|
| - std::map<std::string, InputMethodDescriptor> extra_input_method_ids_;
|
| -
|
| - InputMethodWhitelist whitelist_;
|
| -
|
| - // An object which provides miscellaneous input method utility functions. Note
|
| - // that |util_| is required to initialize |xkeyboard_|.
|
| - InputMethodUtil util_;
|
| -
|
| - // An object for switching XKB layouts and keyboard status like caps lock and
|
| - // auto-repeat interval.
|
| - scoped_ptr<XKeyboard> xkeyboard_;
|
| +namespace {
|
| +InputMethodManager* g_input_method_manager = NULL;
|
| +} // namespace
|
|
|
| - // An object which monitors a notification from the browser to keep track of
|
| - // the browser state (not logged in, logged in, etc.).
|
| - scoped_ptr<BrowserStateMonitor> browser_state_monitor_;
|
| +// static
|
| +void InputMethodManager::Initialize() {
|
| + DCHECK(!g_input_method_manager);
|
| + InputMethodManagerImpl* impl = new InputMethodManagerImpl;
|
| + impl->Init();
|
| + g_input_method_manager = impl;
|
| + VLOG(1) << "InputMethodManager initialized";
|
| +}
|
|
|
| - // true when DisableHotkeys() is called to temporarily disable IME hotkeys.
|
| - // EnableHotkeys() resets the flag to the default value, false.
|
| - bool ignore_hotkeys_;
|
| +// static
|
| +void InputMethodManager::InitializeForTesting(
|
| + InputMethodManager* mock_manager) {
|
| + DCHECK(!g_input_method_manager);
|
| + g_input_method_manager = mock_manager;
|
| + VLOG(1) << "InputMethodManager for testing initialized";
|
| +}
|
|
|
| - DISALLOW_COPY_AND_ASSIGN(InputMethodManagerImpl);
|
| -};
|
| +// static
|
| +void InputMethodManager::Shutdown() {
|
| + delete g_input_method_manager;
|
| + g_input_method_manager = NULL;
|
| + VLOG(1) << "InputMethodManager shutdown";
|
| +}
|
|
|
| // static
|
| InputMethodManager* InputMethodManager::GetInstance() {
|
| - return InputMethodManagerImpl::GetInstance();
|
| + DCHECK(g_input_method_manager);
|
| + return g_input_method_manager;
|
| }
|
|
|
| } // namespace input_method
|
|
|