1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "ui/base/ime/input_method_base.h" 6 7 #include "base/bind.h" 8 #include "base/logging.h" 9 #include "base/message_loop/message_loop.h" 10 #include "ui/base/ime/input_method_delegate.h" 11 #include "ui/base/ime/input_method_observer.h" 12 #include "ui/base/ime/text_input_client.h" 13 #include "ui/base/ime/text_input_focus_manager.h" 14 #include "ui/base/ui_base_switches_util.h" 15 #include "ui/events/event.h" 16 17 namespace ui { 18 19 InputMethodBase::InputMethodBase() 20 : delegate_(NULL), 21 text_input_client_(NULL), 22 system_toplevel_window_focused_(false) { 23 } 24 25 InputMethodBase::~InputMethodBase() { 26 FOR_EACH_OBSERVER(InputMethodObserver, 27 observer_list_, 28 OnInputMethodDestroyed(this)); 29 } 30 31 void InputMethodBase::SetDelegate(internal::InputMethodDelegate* delegate) { 32 delegate_ = delegate; 33 } 34 35 void InputMethodBase::Init(bool focused) { 36 if (focused) 37 OnFocus(); 38 } 39 40 void InputMethodBase::OnFocus() { 41 DCHECK(!system_toplevel_window_focused_); 42 system_toplevel_window_focused_ = true; 43 } 44 45 void InputMethodBase::OnBlur() { 46 DCHECK(system_toplevel_window_focused_); 47 system_toplevel_window_focused_ = false; 48 } 49 50 void InputMethodBase::SetFocusedTextInputClient(TextInputClient* client) { 51 SetFocusedTextInputClientInternal(client); 52 } 53 54 void InputMethodBase::DetachTextInputClient(TextInputClient* client) { 55 if (text_input_client_ != client) 56 return; 57 SetFocusedTextInputClientInternal(NULL); 58 } 59 60 TextInputClient* InputMethodBase::GetTextInputClient() const { 61 if (switches::IsTextInputFocusManagerEnabled()) 62 return TextInputFocusManager::GetInstance()->GetFocusedTextInputClient(); 63 64 return system_toplevel_window_focused_ ? text_input_client_ : NULL; 65 } 66 67 void InputMethodBase::OnTextInputTypeChanged(const TextInputClient* client) { 68 if (!IsTextInputClientFocused(client)) 69 return; 70 NotifyTextInputStateChanged(client); 71 } 72 73 TextInputType InputMethodBase::GetTextInputType() const { 74 TextInputClient* client = GetTextInputClient(); 75 return client ? client->GetTextInputType() : TEXT_INPUT_TYPE_NONE; 76 } 77 78 TextInputMode InputMethodBase::GetTextInputMode() const { 79 TextInputClient* client = GetTextInputClient(); 80 return client ? client->GetTextInputMode() : TEXT_INPUT_MODE_DEFAULT; 81 } 82 83 bool InputMethodBase::CanComposeInline() const { 84 TextInputClient* client = GetTextInputClient(); 85 return client ? client->CanComposeInline() : true; 86 } 87 88 void InputMethodBase::ShowImeIfNeeded() { 89 FOR_EACH_OBSERVER(InputMethodObserver, observer_list_, OnShowImeIfNeeded()); 90 } 91 92 void InputMethodBase::AddObserver(InputMethodObserver* observer) { 93 observer_list_.AddObserver(observer); 94 } 95 96 void InputMethodBase::RemoveObserver(InputMethodObserver* observer) { 97 observer_list_.RemoveObserver(observer); 98 } 99 100 bool InputMethodBase::IsTextInputClientFocused(const TextInputClient* client) { 101 return client && (client == GetTextInputClient()); 102 } 103 104 bool InputMethodBase::IsTextInputTypeNone() const { 105 return GetTextInputType() == TEXT_INPUT_TYPE_NONE; 106 } 107 108 void InputMethodBase::OnInputMethodChanged() const { 109 TextInputClient* client = GetTextInputClient(); 110 if (!IsTextInputTypeNone()) 111 client->OnInputMethodChanged(); 112 } 113 114 bool InputMethodBase::DispatchKeyEventPostIME( 115 const ui::KeyEvent& event) const { 116 if (!delegate_) 117 return false; 118 119 return delegate_->DispatchKeyEventPostIME(event); 120 } 121 122 void InputMethodBase::NotifyTextInputStateChanged( 123 const TextInputClient* client) { 124 FOR_EACH_OBSERVER(InputMethodObserver, 125 observer_list_, 126 OnTextInputStateChanged(client)); 127 } 128 129 void InputMethodBase::SetFocusedTextInputClientInternal( 130 TextInputClient* client) { 131 if (switches::IsTextInputFocusManagerEnabled()) 132 return; 133 134 TextInputClient* old = text_input_client_; 135 if (old == client) 136 return; 137 OnWillChangeFocusedClient(old, client); 138 text_input_client_ = client; // NULL allowed. 139 OnDidChangeFocusedClient(old, client); 140 NotifyTextInputStateChanged(text_input_client_); 141 } 142 143 void InputMethodBase::OnCandidateWindowShown() { 144 base::MessageLoop::current()->PostTask( 145 FROM_HERE, 146 base::Bind(&InputMethodBase::CandidateWindowShownCallback, AsWeakPtr())); 147 } 148 149 void InputMethodBase::OnCandidateWindowUpdated() { 150 base::MessageLoop::current()->PostTask( 151 FROM_HERE, 152 base::Bind(&InputMethodBase::CandidateWindowUpdatedCallback, 153 AsWeakPtr())); 154 } 155 156 void InputMethodBase::OnCandidateWindowHidden() { 157 base::MessageLoop::current()->PostTask( 158 FROM_HERE, 159 base::Bind(&InputMethodBase::CandidateWindowHiddenCallback, AsWeakPtr())); 160 } 161 162 void InputMethodBase::CandidateWindowShownCallback() { 163 if (TextInputClient* text_input_client = GetTextInputClient()) 164 text_input_client->OnCandidateWindowShown(); 165 } 166 167 void InputMethodBase::CandidateWindowUpdatedCallback() { 168 if (TextInputClient* text_input_client = GetTextInputClient()) 169 text_input_client->OnCandidateWindowUpdated(); 170 } 171 172 void InputMethodBase::CandidateWindowHiddenCallback() { 173 if (TextInputClient* text_input_client = GetTextInputClient()) 174 text_input_client->OnCandidateWindowHidden(); 175 } 176 177 } // namespace ui 178