11e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
21e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
31e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// found in the LICENSE file.
41e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
5a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "ui/base/ime/input_method_auralinux.h"
61e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
7f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/environment.h"
81e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "ui/base/ime/linux/linux_input_method_context_factory.h"
91e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "ui/base/ime/text_input_client.h"
101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "ui/events/event.h"
111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)namespace ui {
131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
14a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)InputMethodAuraLinux::InputMethodAuraLinux(
15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    internal::InputMethodDelegate* delegate)
16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    : allowed_to_fire_vkey_process_key_(false), vkey_processkey_flags_(0) {
171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  SetDelegate(delegate);
181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
20a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)InputMethodAuraLinux::~InputMethodAuraLinux() {}
211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Overriden from InputMethod.
231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
24a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void InputMethodAuraLinux::Init(bool focused) {
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CHECK(LinuxInputMethodContextFactory::instance())
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      << "This failure was likely caused because "
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      << "ui::InitializeInputMethod(ForTesting) was not called "
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      << "before instantiating this class.";
291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  input_method_context_ =
301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      LinuxInputMethodContextFactory::instance()->CreateInputMethodContext(
311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          this);
321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  CHECK(input_method_context_.get());
331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  InputMethodBase::Init(focused);
351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (focused) {
371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    input_method_context_->OnTextInputTypeChanged(
381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        GetTextInputClient() ?
391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        GetTextInputClient()->GetTextInputType() :
401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        TEXT_INPUT_TYPE_TEXT);
411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
44a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool InputMethodAuraLinux::OnUntranslatedIMEMessage(
451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const base::NativeEvent& event,
461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    NativeEventResult* result) {
471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return false;
481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
50a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool InputMethodAuraLinux::DispatchKeyEvent(const ui::KeyEvent& event) {
51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(event.type() == ET_KEY_PRESSED || event.type() == ET_KEY_RELEASED);
521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DCHECK(system_toplevel_window_focused());
531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // If no text input client, do nothing.
551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (!GetTextInputClient())
56a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return DispatchKeyEventPostIME(event);
571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Let an IME handle the key event first, and allow to fire a VKEY_PROCESSKEY
59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // event for keydown events.  Note that DOM Level 3 Events Sepc requires that
60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // only keydown events fire keyCode=229 events and not for keyup events.
61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (event.type() == ET_KEY_PRESSED &&
62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      (event.flags() & ui::EF_IME_FABRICATED_KEY) == 0)
63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    AllowToFireProcessKey(event);
64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (input_method_context_->DispatchKeyEvent(event))
651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return true;
66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  StopFiringProcessKey();
671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Otherwise, insert the character.
69a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  const bool handled = DispatchKeyEventPostIME(event);
701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (event.type() == ET_KEY_PRESSED && GetTextInputClient()) {
711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const uint16 ch = event.GetCharacter();
721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (ch) {
731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      GetTextInputClient()->InsertChar(ch, event.flags());
741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      return true;
751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return handled;
781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
80a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void InputMethodAuraLinux::OnTextInputTypeChanged(
811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const TextInputClient* client) {
82f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!IsTextInputClientFocused(client))
83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
84f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  input_method_context_->Reset();
85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // TODO(yoichio): Support inputmode HTML attribute.
86f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  input_method_context_->OnTextInputTypeChanged(client->GetTextInputType());
871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
89a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void InputMethodAuraLinux::OnCaretBoundsChanged(const TextInputClient* client) {
90f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!IsTextInputClientFocused(client))
91f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
92f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  input_method_context_->OnCaretBoundsChanged(
93f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      GetTextInputClient()->GetCaretBounds());
941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
96a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void InputMethodAuraLinux::CancelComposition(const TextInputClient* client) {
971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (!IsTextInputClientFocused(client))
981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return;
991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  input_method_context_->Reset();
1001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  input_method_context_->OnTextInputTypeChanged(client->GetTextInputType());
1011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void InputMethodAuraLinux::OnInputLocaleChanged() {
1041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
106a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)std::string InputMethodAuraLinux::GetInputLocale() {
1071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return "";
1081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
110a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool InputMethodAuraLinux::IsActive() {
111a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // InputMethodAuraLinux is always ready and up.
1121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return true;
1131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
115a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool InputMethodAuraLinux::IsCandidatePopupOpen() const {
1161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // There seems no way to detect candidate windows or any popups.
1171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return false;
1181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Overriden from ui::LinuxInputMethodContextDelegate
1211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
122a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void InputMethodAuraLinux::OnCommit(const base::string16& text) {
123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  MaybeFireProcessKey();
124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!IsTextInputTypeNone())
125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    GetTextInputClient()->InsertText(text);
1261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
128a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void InputMethodAuraLinux::OnPreeditChanged(
1291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const CompositionText& composition_text) {
130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  MaybeFireProcessKey();
1311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  TextInputClient* text_input_client = GetTextInputClient();
1321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (text_input_client)
1331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    text_input_client->SetCompositionText(composition_text);
1341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
136a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void InputMethodAuraLinux::OnPreeditEnd() {
137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  MaybeFireProcessKey();
1381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  TextInputClient* text_input_client = GetTextInputClient();
1391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (text_input_client && text_input_client->HasCompositionText())
1401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    text_input_client->ClearCompositionText();
1411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void InputMethodAuraLinux::OnPreeditStart() {
144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  MaybeFireProcessKey();
145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
1461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Overridden from InputMethodBase.
1481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
149a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void InputMethodAuraLinux::OnDidChangeFocusedClient(
1501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    TextInputClient* focused_before,
1511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    TextInputClient* focused) {
1521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  input_method_context_->Reset();
1531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  input_method_context_->OnTextInputTypeChanged(
1541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      focused ? focused->GetTextInputType() : TEXT_INPUT_TYPE_NONE);
1551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  InputMethodBase::OnDidChangeFocusedClient(focused_before, focused);
1571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Helper functions to support VKEY_PROCESSKEY.
160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void InputMethodAuraLinux::AllowToFireProcessKey(const ui::KeyEvent& event) {
162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  allowed_to_fire_vkey_process_key_ = true;
163cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  vkey_processkey_flags_ = event.flags();
164cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
165cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void InputMethodAuraLinux::MaybeFireProcessKey() {
167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!allowed_to_fire_vkey_process_key_)
168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const ui::KeyEvent fabricated_event(ET_KEY_PRESSED,
171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                      VKEY_PROCESSKEY,
1725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                      vkey_processkey_flags_);
173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DispatchKeyEventPostIME(fabricated_event);
174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  StopFiringProcessKey();
175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void InputMethodAuraLinux::StopFiringProcessKey() {
178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  allowed_to_fire_vkey_process_key_ = false;
179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  vkey_processkey_flags_ = 0;
180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}  // namespace ui
183