Home | History | Annotate | Download | only in ime
      1 // Copyright 2013 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_auralinux.h"
      6 
      7 #include "base/environment.h"
      8 #include "ui/base/ime/linux/linux_input_method_context_factory.h"
      9 #include "ui/base/ime/text_input_client.h"
     10 #include "ui/events/event.h"
     11 
     12 namespace ui {
     13 
     14 InputMethodAuraLinux::InputMethodAuraLinux(
     15     internal::InputMethodDelegate* delegate)
     16     : allowed_to_fire_vkey_process_key_(false), vkey_processkey_flags_(0) {
     17   SetDelegate(delegate);
     18 }
     19 
     20 InputMethodAuraLinux::~InputMethodAuraLinux() {}
     21 
     22 // Overriden from InputMethod.
     23 
     24 void InputMethodAuraLinux::Init(bool focused) {
     25   CHECK(LinuxInputMethodContextFactory::instance())
     26       << "This failure was likely caused because "
     27       << "ui::InitializeInputMethod(ForTesting) was not called "
     28       << "before instantiating this class.";
     29   input_method_context_ =
     30       LinuxInputMethodContextFactory::instance()->CreateInputMethodContext(
     31           this);
     32   CHECK(input_method_context_.get());
     33 
     34   InputMethodBase::Init(focused);
     35 
     36   if (focused) {
     37     input_method_context_->OnTextInputTypeChanged(
     38         GetTextInputClient() ?
     39         GetTextInputClient()->GetTextInputType() :
     40         TEXT_INPUT_TYPE_TEXT);
     41   }
     42 }
     43 
     44 bool InputMethodAuraLinux::OnUntranslatedIMEMessage(
     45     const base::NativeEvent& event,
     46     NativeEventResult* result) {
     47   return false;
     48 }
     49 
     50 bool InputMethodAuraLinux::DispatchKeyEvent(const ui::KeyEvent& event) {
     51   DCHECK(event.type() == ET_KEY_PRESSED || event.type() == ET_KEY_RELEASED);
     52   DCHECK(system_toplevel_window_focused());
     53 
     54   // If no text input client, do nothing.
     55   if (!GetTextInputClient())
     56     return DispatchKeyEventPostIME(event);
     57 
     58   // Let an IME handle the key event first, and allow to fire a VKEY_PROCESSKEY
     59   // event for keydown events.  Note that DOM Level 3 Events Sepc requires that
     60   // only keydown events fire keyCode=229 events and not for keyup events.
     61   if (event.type() == ET_KEY_PRESSED &&
     62       (event.flags() & ui::EF_IME_FABRICATED_KEY) == 0)
     63     AllowToFireProcessKey(event);
     64   if (input_method_context_->DispatchKeyEvent(event))
     65     return true;
     66   StopFiringProcessKey();
     67 
     68   // Otherwise, insert the character.
     69   const bool handled = DispatchKeyEventPostIME(event);
     70   if (event.type() == ET_KEY_PRESSED && GetTextInputClient()) {
     71     const uint16 ch = event.GetCharacter();
     72     if (ch) {
     73       GetTextInputClient()->InsertChar(ch, event.flags());
     74       return true;
     75     }
     76   }
     77   return handled;
     78 }
     79 
     80 void InputMethodAuraLinux::OnTextInputTypeChanged(
     81     const TextInputClient* client) {
     82   if (!IsTextInputClientFocused(client))
     83     return;
     84   input_method_context_->Reset();
     85   // TODO(yoichio): Support inputmode HTML attribute.
     86   input_method_context_->OnTextInputTypeChanged(client->GetTextInputType());
     87 }
     88 
     89 void InputMethodAuraLinux::OnCaretBoundsChanged(const TextInputClient* client) {
     90   if (!IsTextInputClientFocused(client))
     91     return;
     92   input_method_context_->OnCaretBoundsChanged(
     93       GetTextInputClient()->GetCaretBounds());
     94 }
     95 
     96 void InputMethodAuraLinux::CancelComposition(const TextInputClient* client) {
     97   if (!IsTextInputClientFocused(client))
     98     return;
     99   input_method_context_->Reset();
    100   input_method_context_->OnTextInputTypeChanged(client->GetTextInputType());
    101 }
    102 
    103 void InputMethodAuraLinux::OnInputLocaleChanged() {
    104 }
    105 
    106 std::string InputMethodAuraLinux::GetInputLocale() {
    107   return "";
    108 }
    109 
    110 bool InputMethodAuraLinux::IsActive() {
    111   // InputMethodAuraLinux is always ready and up.
    112   return true;
    113 }
    114 
    115 bool InputMethodAuraLinux::IsCandidatePopupOpen() const {
    116   // There seems no way to detect candidate windows or any popups.
    117   return false;
    118 }
    119 
    120 // Overriden from ui::LinuxInputMethodContextDelegate
    121 
    122 void InputMethodAuraLinux::OnCommit(const base::string16& text) {
    123   MaybeFireProcessKey();
    124   if (!IsTextInputTypeNone())
    125     GetTextInputClient()->InsertText(text);
    126 }
    127 
    128 void InputMethodAuraLinux::OnPreeditChanged(
    129     const CompositionText& composition_text) {
    130   MaybeFireProcessKey();
    131   TextInputClient* text_input_client = GetTextInputClient();
    132   if (text_input_client)
    133     text_input_client->SetCompositionText(composition_text);
    134 }
    135 
    136 void InputMethodAuraLinux::OnPreeditEnd() {
    137   MaybeFireProcessKey();
    138   TextInputClient* text_input_client = GetTextInputClient();
    139   if (text_input_client && text_input_client->HasCompositionText())
    140     text_input_client->ClearCompositionText();
    141 }
    142 
    143 void InputMethodAuraLinux::OnPreeditStart() {
    144   MaybeFireProcessKey();
    145 }
    146 
    147 // Overridden from InputMethodBase.
    148 
    149 void InputMethodAuraLinux::OnDidChangeFocusedClient(
    150     TextInputClient* focused_before,
    151     TextInputClient* focused) {
    152   input_method_context_->Reset();
    153   input_method_context_->OnTextInputTypeChanged(
    154       focused ? focused->GetTextInputType() : TEXT_INPUT_TYPE_NONE);
    155 
    156   InputMethodBase::OnDidChangeFocusedClient(focused_before, focused);
    157 }
    158 
    159 // Helper functions to support VKEY_PROCESSKEY.
    160 
    161 void InputMethodAuraLinux::AllowToFireProcessKey(const ui::KeyEvent& event) {
    162   allowed_to_fire_vkey_process_key_ = true;
    163   vkey_processkey_flags_ = event.flags();
    164 }
    165 
    166 void InputMethodAuraLinux::MaybeFireProcessKey() {
    167   if (!allowed_to_fire_vkey_process_key_)
    168     return;
    169 
    170   const ui::KeyEvent fabricated_event(ET_KEY_PRESSED,
    171                                       VKEY_PROCESSKEY,
    172                                       vkey_processkey_flags_,
    173                                       false);  // is_char
    174   DispatchKeyEventPostIME(fabricated_event);
    175   StopFiringProcessKey();
    176 }
    177 
    178 void InputMethodAuraLinux::StopFiringProcessKey() {
    179   allowed_to_fire_vkey_process_key_ = false;
    180   vkey_processkey_flags_ = 0;
    181 }
    182 
    183 }  // namespace ui
    184