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.
5 #include "ui/views/ime/input_method_bridge.h"
7 #include "ui/base/ime/input_method.h"
8 #include "ui/events/event.h"
9 #include "ui/gfx/rect.h"
10 #include "ui/views/view.h"
11 #include "ui/views/widget/widget.h"
15 InputMethodBridge::InputMethodBridge(internal::InputMethodDelegate* delegate,
16 ui::InputMethod* host,
17 bool shared_input_method)
19 shared_input_method_(shared_input_method) {
21 SetDelegate(delegate);
24 InputMethodBridge::~InputMethodBridge() {
25 // By the time we get here it's very likely |widget_|'s NativeWidget has been
26 // destroyed. This means any calls to |widget_| that go to the NativeWidget,
27 // such as IsActive(), will crash. SetFocusedTextInputClient() may callback to
28 // this and go into |widget_|. NULL out |widget_| so we don't attempt to use
31 host_->DetachTextInputClient(this);
34 void InputMethodBridge::OnFocus() {
35 // Direct the shared IME to send TextInputClient messages to |this| object.
36 if (shared_input_method_ || !host_->GetTextInputClient())
37 host_->SetFocusedTextInputClient(this);
39 // TODO(yusukes): We don't need to call OnTextInputTypeChanged() once we move
40 // text input type tracker code to ui::InputMethodBase.
42 OnTextInputTypeChanged(GetFocusedView());
45 void InputMethodBridge::OnBlur() {
46 if (HasCompositionText()) {
47 ConfirmCompositionText();
48 host_->CancelComposition(this);
51 if (host_->GetTextInputClient() == this)
52 host_->SetFocusedTextInputClient(NULL);
55 bool InputMethodBridge::OnUntranslatedIMEMessage(const base::NativeEvent& event,
56 NativeEventResult* result) {
57 return host_->OnUntranslatedIMEMessage(event, result);
60 void InputMethodBridge::DispatchKeyEvent(const ui::KeyEvent& key) {
61 DCHECK(key.type() == ui::ET_KEY_PRESSED || key.type() == ui::ET_KEY_RELEASED);
63 // We can just dispatch the event here since the |key| is already processed by
64 // the system-wide IME.
65 DispatchKeyEventPostIME(key);
68 void InputMethodBridge::OnTextInputTypeChanged(View* view) {
69 if (IsViewFocused(view))
70 host_->OnTextInputTypeChanged(this);
71 InputMethodBase::OnTextInputTypeChanged(view);
74 void InputMethodBridge::OnCaretBoundsChanged(View* view) {
75 if (IsViewFocused(view) && !IsTextInputTypeNone())
76 host_->OnCaretBoundsChanged(this);
79 void InputMethodBridge::CancelComposition(View* view) {
80 if (IsViewFocused(view))
81 host_->CancelComposition(this);
84 void InputMethodBridge::OnInputLocaleChanged() {
85 return host_->OnInputLocaleChanged();
88 std::string InputMethodBridge::GetInputLocale() {
89 return host_->GetInputLocale();
92 base::i18n::TextDirection InputMethodBridge::GetInputTextDirection() {
93 return host_->GetInputTextDirection();
96 bool InputMethodBridge::IsActive() {
97 return host_->IsActive();
100 bool InputMethodBridge::IsCandidatePopupOpen() const {
101 return host_->IsCandidatePopupOpen();
104 // Overridden from TextInputClient. Forward an event from the system-wide IME
105 // to the text input |client|, which is e.g. views::NativeTextfieldViews.
106 void InputMethodBridge::SetCompositionText(
107 const ui::CompositionText& composition) {
108 TextInputClient* client = GetTextInputClient();
110 client->SetCompositionText(composition);
113 void InputMethodBridge::ConfirmCompositionText() {
114 TextInputClient* client = GetTextInputClient();
116 client->ConfirmCompositionText();
119 void InputMethodBridge::ClearCompositionText() {
120 TextInputClient* client = GetTextInputClient();
122 client->ClearCompositionText();
125 void InputMethodBridge::InsertText(const string16& text) {
126 TextInputClient* client = GetTextInputClient();
128 client->InsertText(text);
131 void InputMethodBridge::InsertChar(char16 ch, int flags) {
132 TextInputClient* client = GetTextInputClient();
134 client->InsertChar(ch, flags);
137 gfx::NativeWindow InputMethodBridge::GetAttachedWindow() const {
138 TextInputClient* client = GetTextInputClient();
140 client->GetAttachedWindow() : static_cast<gfx::NativeWindow>(NULL);
143 ui::TextInputType InputMethodBridge::GetTextInputType() const {
144 TextInputClient* client = GetTextInputClient();
145 return client ? client->GetTextInputType() : ui::TEXT_INPUT_TYPE_NONE;
148 ui::TextInputMode InputMethodBridge::GetTextInputMode() const {
149 TextInputClient* client = GetTextInputClient();
150 return client ? client->GetTextInputMode() : ui::TEXT_INPUT_MODE_DEFAULT;
153 bool InputMethodBridge::CanComposeInline() const {
154 TextInputClient* client = GetTextInputClient();
155 return client ? client->CanComposeInline() : true;
158 gfx::Rect InputMethodBridge::GetCaretBounds() const {
159 TextInputClient* client = GetTextInputClient();
163 return client->GetCaretBounds();
166 bool InputMethodBridge::GetCompositionCharacterBounds(uint32 index,
167 gfx::Rect* rect) const {
169 TextInputClient* client = GetTextInputClient();
173 return client->GetCompositionCharacterBounds(index, rect);
176 bool InputMethodBridge::HasCompositionText() const {
177 TextInputClient* client = GetTextInputClient();
178 return client ? client->HasCompositionText() : false;
181 bool InputMethodBridge::GetTextRange(gfx::Range* range) const {
182 TextInputClient* client = GetTextInputClient();
183 return client ? client->GetTextRange(range) : false;
186 bool InputMethodBridge::GetCompositionTextRange(gfx::Range* range) const {
187 TextInputClient* client = GetTextInputClient();
188 return client ? client->GetCompositionTextRange(range) : false;
191 bool InputMethodBridge::GetSelectionRange(gfx::Range* range) const {
192 TextInputClient* client = GetTextInputClient();
193 return client ? client->GetSelectionRange(range) : false;
196 bool InputMethodBridge::SetSelectionRange(const gfx::Range& range) {
197 TextInputClient* client = GetTextInputClient();
198 return client ? client->SetSelectionRange(range) : false;
201 bool InputMethodBridge::DeleteRange(const gfx::Range& range) {
202 TextInputClient* client = GetTextInputClient();
203 return client ? client->DeleteRange(range) : false;
206 bool InputMethodBridge::GetTextFromRange(const gfx::Range& range,
207 string16* text) const {
208 TextInputClient* client = GetTextInputClient();
209 return client ? client->GetTextFromRange(range, text) : false;
212 void InputMethodBridge::OnInputMethodChanged() {
213 TextInputClient* client = GetTextInputClient();
215 client->OnInputMethodChanged();
218 bool InputMethodBridge::ChangeTextDirectionAndLayoutAlignment(
219 base::i18n::TextDirection direction) {
220 TextInputClient* client = GetTextInputClient();
222 client->ChangeTextDirectionAndLayoutAlignment(direction) : false;
225 void InputMethodBridge::ExtendSelectionAndDelete(size_t before, size_t after) {
226 TextInputClient* client = GetTextInputClient();
228 client->ExtendSelectionAndDelete(before, after);
231 void InputMethodBridge::EnsureCaretInRect(const gfx::Rect& rect) {
232 TextInputClient* client = GetTextInputClient();
234 client->EnsureCaretInRect(rect);
237 // Overridden from FocusChangeListener.
238 void InputMethodBridge::OnWillChangeFocus(View* focused_before, View* focused) {
239 if (HasCompositionText()) {
240 ConfirmCompositionText();
241 CancelComposition(focused_before);
245 void InputMethodBridge::OnDidChangeFocus(View* focused_before, View* focused) {
246 DCHECK_EQ(GetFocusedView(), focused);
247 OnTextInputTypeChanged(focused);
248 OnCaretBoundsChanged(focused);
251 ui::InputMethod* InputMethodBridge::GetHostInputMethod() const {