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/events/event.h" 14 15 namespace ui { 16 17 InputMethodBase::InputMethodBase() 18 : delegate_(NULL), 19 text_input_client_(NULL), 20 system_toplevel_window_focused_(false) { 21 } 22 23 InputMethodBase::~InputMethodBase() { 24 FOR_EACH_OBSERVER(InputMethodObserver, 25 observer_list_, 26 OnInputMethodDestroyed(this)); 27 } 28 29 void InputMethodBase::SetDelegate(internal::InputMethodDelegate* delegate) { 30 delegate_ = delegate; 31 } 32 33 void InputMethodBase::Init(bool focused) { 34 if (focused) 35 OnFocus(); 36 } 37 38 void InputMethodBase::OnFocus() { 39 DCHECK(!system_toplevel_window_focused_); 40 system_toplevel_window_focused_ = true; 41 } 42 43 void InputMethodBase::OnBlur() { 44 DCHECK(system_toplevel_window_focused_); 45 system_toplevel_window_focused_ = false; 46 } 47 48 void InputMethodBase::SetFocusedTextInputClient(TextInputClient* client) { 49 SetFocusedTextInputClientInternal(client); 50 } 51 52 void InputMethodBase::DetachTextInputClient(TextInputClient* client) { 53 if (text_input_client_ != client) 54 return; 55 SetFocusedTextInputClientInternal(NULL); 56 } 57 58 TextInputClient* InputMethodBase::GetTextInputClient() const { 59 return system_toplevel_window_focused_ ? text_input_client_ : NULL; 60 } 61 62 void InputMethodBase::OnTextInputTypeChanged(const TextInputClient* client) { 63 if (!IsTextInputClientFocused(client)) 64 return; 65 NotifyTextInputStateChanged(client); 66 } 67 68 TextInputType InputMethodBase::GetTextInputType() const { 69 TextInputClient* client = GetTextInputClient(); 70 return client ? client->GetTextInputType() : TEXT_INPUT_TYPE_NONE; 71 } 72 73 TextInputMode InputMethodBase::GetTextInputMode() const { 74 TextInputClient* client = GetTextInputClient(); 75 return client ? client->GetTextInputMode() : TEXT_INPUT_MODE_DEFAULT; 76 } 77 78 bool InputMethodBase::CanComposeInline() const { 79 TextInputClient* client = GetTextInputClient(); 80 return client ? client->CanComposeInline() : true; 81 } 82 83 void InputMethodBase::AddObserver(InputMethodObserver* observer) { 84 observer_list_.AddObserver(observer); 85 } 86 87 void InputMethodBase::RemoveObserver(InputMethodObserver* observer) { 88 observer_list_.RemoveObserver(observer); 89 } 90 91 bool InputMethodBase::IsTextInputClientFocused(const TextInputClient* client) { 92 return client && (client == GetTextInputClient()); 93 } 94 95 bool InputMethodBase::IsTextInputTypeNone() const { 96 return GetTextInputType() == TEXT_INPUT_TYPE_NONE; 97 } 98 99 void InputMethodBase::OnInputMethodChanged() const { 100 TextInputClient* client = GetTextInputClient(); 101 if (!IsTextInputTypeNone()) 102 client->OnInputMethodChanged(); 103 } 104 105 bool InputMethodBase::DispatchKeyEventPostIME( 106 const ui::KeyEvent& event) const { 107 if (!delegate_) 108 return false; 109 110 if (!event.HasNativeEvent()) 111 return delegate_->DispatchFabricatedKeyEventPostIME( 112 event.type(), event.key_code(), event.flags()); 113 114 return delegate_->DispatchKeyEventPostIME(event.native_event()); 115 } 116 117 void InputMethodBase::NotifyTextInputStateChanged( 118 const TextInputClient* client) { 119 FOR_EACH_OBSERVER(InputMethodObserver, 120 observer_list_, 121 OnTextInputStateChanged(client)); 122 } 123 124 void InputMethodBase::SetFocusedTextInputClientInternal( 125 TextInputClient* client) { 126 TextInputClient* old = text_input_client_; 127 if (old == client) 128 return; 129 OnWillChangeFocusedClient(old, client); 130 text_input_client_ = client; // NULL allowed. 131 OnDidChangeFocusedClient(old, client); 132 NotifyTextInputStateChanged(text_input_client_); 133 } 134 135 void InputMethodBase::OnCandidateWindowShown() { 136 base::MessageLoop::current()->PostTask( 137 FROM_HERE, 138 base::Bind(&InputMethodBase::CandidateWindowShownCallback, AsWeakPtr())); 139 } 140 141 void InputMethodBase::OnCandidateWindowUpdated() { 142 base::MessageLoop::current()->PostTask( 143 FROM_HERE, 144 base::Bind(&InputMethodBase::CandidateWindowUpdatedCallback, 145 AsWeakPtr())); 146 } 147 148 void InputMethodBase::OnCandidateWindowHidden() { 149 base::MessageLoop::current()->PostTask( 150 FROM_HERE, 151 base::Bind(&InputMethodBase::CandidateWindowHiddenCallback, AsWeakPtr())); 152 } 153 154 void InputMethodBase::CandidateWindowShownCallback() { 155 if (text_input_client_) 156 text_input_client_->OnCandidateWindowShown(); 157 } 158 159 void InputMethodBase::CandidateWindowUpdatedCallback() { 160 if (text_input_client_) 161 text_input_client_->OnCandidateWindowUpdated(); 162 } 163 164 void InputMethodBase::CandidateWindowHiddenCallback() { 165 if (text_input_client_) 166 text_input_client_->OnCandidateWindowHidden(); 167 } 168 169 } // namespace ui 170