Home | History | Annotate | Download | only in ime
      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