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 DispatchKeyEventPostIME(fabricated_event); 174 StopFiringProcessKey(); 175 } 176 177 void InputMethodAuraLinux::StopFiringProcessKey() { 178 allowed_to_fire_vkey_process_key_ = false; 179 vkey_processkey_flags_ = 0; 180 } 181 182 } // namespace ui 183