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/views/ime/input_method_bridge.h" 6 7#include "ui/base/events/event.h" 8#include "ui/base/ime/input_method.h" 9#include "ui/gfx/rect.h" 10#include "ui/views/view.h" 11#include "ui/views/widget/widget.h" 12 13namespace views { 14 15InputMethodBridge::InputMethodBridge(internal::InputMethodDelegate* delegate, 16 ui::InputMethod* host, 17 bool shared_input_method) 18 : host_(host), 19 shared_input_method_(shared_input_method), 20 context_focused_(false) { 21 DCHECK(host_); 22 SetDelegate(delegate); 23} 24 25InputMethodBridge::~InputMethodBridge() { 26 // By the time we get here it's very likely |widget_|'s NativeWidget has been 27 // destroyed. This means any calls to |widget_| that go to the NativeWidget, 28 // such as IsActive(), will crash. SetFocusedTextInputClient() may callback to 29 // this and go into |widget_|. NULL out |widget_| so we don't attempt to use 30 // it. 31 DetachFromWidget(); 32 if (host_->GetTextInputClient() == this) 33 host_->SetFocusedTextInputClient(NULL); 34} 35 36void InputMethodBridge::OnFocus() { 37 // Direct the shared IME to send TextInputClient messages to |this| object. 38 if (shared_input_method_ || !host_->GetTextInputClient()) 39 host_->SetFocusedTextInputClient(this); 40 41 // TODO(yusukes): We don't need to call OnTextInputTypeChanged() once we move 42 // text input type tracker code to ui::InputMethodBase. 43 if (GetFocusedView()) 44 OnTextInputTypeChanged(GetFocusedView()); 45} 46 47void InputMethodBridge::OnBlur() { 48 if (HasCompositionText()) { 49 ConfirmCompositionText(); 50 host_->CancelComposition(this); 51 } 52 53 if (host_->GetTextInputClient() == this) 54 host_->SetFocusedTextInputClient(NULL); 55} 56 57bool InputMethodBridge::OnUntranslatedIMEMessage(const base::NativeEvent& event, 58 NativeEventResult* result) { 59 return host_->OnUntranslatedIMEMessage(event, result); 60} 61 62void InputMethodBridge::DispatchKeyEvent(const ui::KeyEvent& key) { 63 DCHECK(key.type() == ui::ET_KEY_PRESSED || key.type() == ui::ET_KEY_RELEASED); 64 65 // We can just dispatch the event here since the |key| is already processed by 66 // the system-wide IME. 67 DispatchKeyEventPostIME(key); 68} 69 70void InputMethodBridge::OnTextInputTypeChanged(View* view) { 71 if (IsViewFocused(view)) 72 host_->OnTextInputTypeChanged(this); 73 InputMethodBase::OnTextInputTypeChanged(view); 74} 75 76void InputMethodBridge::OnCaretBoundsChanged(View* view) { 77 if (IsViewFocused(view) && !IsTextInputTypeNone()) 78 host_->OnCaretBoundsChanged(this); 79} 80 81void InputMethodBridge::CancelComposition(View* view) { 82 if (IsViewFocused(view)) 83 host_->CancelComposition(this); 84} 85 86void InputMethodBridge::OnInputLocaleChanged() { 87 return host_->OnInputLocaleChanged(); 88} 89 90std::string InputMethodBridge::GetInputLocale() { 91 return host_->GetInputLocale(); 92} 93 94base::i18n::TextDirection InputMethodBridge::GetInputTextDirection() { 95 return host_->GetInputTextDirection(); 96} 97 98bool InputMethodBridge::IsActive() { 99 return host_->IsActive(); 100} 101 102bool InputMethodBridge::IsCandidatePopupOpen() const { 103 return host_->IsCandidatePopupOpen(); 104} 105 106// Overridden from TextInputClient. Forward an event from the system-wide IME 107// to the text input |client|, which is e.g. views::NativeTextfieldViews. 108void InputMethodBridge::SetCompositionText( 109 const ui::CompositionText& composition) { 110 TextInputClient* client = GetTextInputClient(); 111 if (client) 112 client->SetCompositionText(composition); 113} 114 115void InputMethodBridge::ConfirmCompositionText() { 116 TextInputClient* client = GetTextInputClient(); 117 if (client) 118 client->ConfirmCompositionText(); 119} 120 121void InputMethodBridge::ClearCompositionText() { 122 TextInputClient* client = GetTextInputClient(); 123 if (client) 124 client->ClearCompositionText(); 125} 126 127void InputMethodBridge::InsertText(const string16& text) { 128 TextInputClient* client = GetTextInputClient(); 129 if (client) 130 client->InsertText(text); 131} 132 133void InputMethodBridge::InsertChar(char16 ch, int flags) { 134 TextInputClient* client = GetTextInputClient(); 135 if (client) 136 client->InsertChar(ch, flags); 137} 138 139gfx::NativeWindow InputMethodBridge::GetAttachedWindow() const { 140 TextInputClient* client = GetTextInputClient(); 141 return client ? 142 client->GetAttachedWindow() : static_cast<gfx::NativeWindow>(NULL); 143} 144 145ui::TextInputType InputMethodBridge::GetTextInputType() const { 146 TextInputClient* client = GetTextInputClient(); 147 return client ? client->GetTextInputType() : ui::TEXT_INPUT_TYPE_NONE; 148} 149 150ui::TextInputMode InputMethodBridge::GetTextInputMode() const { 151 TextInputClient* client = GetTextInputClient(); 152 return client ? client->GetTextInputMode() : ui::TEXT_INPUT_MODE_DEFAULT; 153} 154 155bool InputMethodBridge::CanComposeInline() const { 156 TextInputClient* client = GetTextInputClient(); 157 return client ? client->CanComposeInline() : true; 158} 159 160gfx::Rect InputMethodBridge::GetCaretBounds() { 161 TextInputClient* client = GetTextInputClient(); 162 if (!client) 163 return gfx::Rect(); 164 165 return client->GetCaretBounds(); 166} 167 168bool InputMethodBridge::GetCompositionCharacterBounds(uint32 index, 169 gfx::Rect* rect) { 170 DCHECK(rect); 171 TextInputClient* client = GetTextInputClient(); 172 if (!client) 173 return false; 174 175 return client->GetCompositionCharacterBounds(index, rect); 176} 177 178bool InputMethodBridge::HasCompositionText() { 179 TextInputClient* client = GetTextInputClient(); 180 return client ? client->HasCompositionText() : false; 181} 182 183bool InputMethodBridge::GetTextRange(ui::Range* range) { 184 TextInputClient* client = GetTextInputClient(); 185 return client ? client->GetTextRange(range) : false; 186} 187 188bool InputMethodBridge::GetCompositionTextRange(ui::Range* range) { 189 TextInputClient* client = GetTextInputClient(); 190 return client ? client->GetCompositionTextRange(range) : false; 191} 192 193bool InputMethodBridge::GetSelectionRange(ui::Range* range) { 194 TextInputClient* client = GetTextInputClient(); 195 return client ? client->GetSelectionRange(range) : false; 196} 197 198bool InputMethodBridge::SetSelectionRange(const ui::Range& range) { 199 TextInputClient* client = GetTextInputClient(); 200 return client ? client->SetSelectionRange(range) : false; 201} 202 203bool InputMethodBridge::DeleteRange(const ui::Range& range) { 204 TextInputClient* client = GetTextInputClient(); 205 return client ? client->DeleteRange(range) : false; 206} 207 208bool InputMethodBridge::GetTextFromRange( 209 const ui::Range& range, string16* text) { 210 TextInputClient* client = GetTextInputClient(); 211 return client ? client->GetTextFromRange(range, text) : false; 212} 213 214void InputMethodBridge::OnInputMethodChanged() { 215 TextInputClient* client = GetTextInputClient(); 216 if (client) 217 client->OnInputMethodChanged(); 218} 219 220bool InputMethodBridge::ChangeTextDirectionAndLayoutAlignment( 221 base::i18n::TextDirection direction) { 222 TextInputClient* client = GetTextInputClient(); 223 return client ? 224 client->ChangeTextDirectionAndLayoutAlignment(direction) : false; 225} 226 227void InputMethodBridge::ExtendSelectionAndDelete(size_t before, size_t after) { 228 TextInputClient* client = GetTextInputClient(); 229 if (client) 230 client->ExtendSelectionAndDelete(before, after); 231} 232 233void InputMethodBridge::EnsureCaretInRect(const gfx::Rect& rect) { 234 TextInputClient* client = GetTextInputClient(); 235 if (client) 236 client->EnsureCaretInRect(rect); 237} 238 239// Overridden from FocusChangeListener. 240void InputMethodBridge::OnWillChangeFocus(View* focused_before, View* focused) { 241 if (HasCompositionText()) { 242 ConfirmCompositionText(); 243 CancelComposition(focused_before); 244 } 245} 246 247void InputMethodBridge::OnDidChangeFocus(View* focused_before, View* focused) { 248 DCHECK_EQ(GetFocusedView(), focused); 249 OnTextInputTypeChanged(focused); 250 OnCaretBoundsChanged(focused); 251} 252 253ui::InputMethod* InputMethodBridge::GetHostInputMethod() const { 254 return host_; 255} 256 257 258} // namespace views 259