blob: e2a557f7b02b260c3b28536848cc7b53934d4421 [file] [log] [blame]
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/base/ime/input_method_base.h"
#include <tuple>
#include "base/check.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/observer_list.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "ui/base/ime/ime_key_event_dispatcher.h"
#include "ui/base/ime/input_method_observer.h"
#include "ui/base/ime/text_input_client.h"
#include "ui/base/ime/text_input_flags.h"
#include "ui/base/ime/virtual_keyboard_controller_stub.h"
#include "ui/events/event.h"
namespace ui {
InputMethodBase::InputMethodBase(
ImeKeyEventDispatcher* ime_key_event_dispatcher)
: InputMethodBase(ime_key_event_dispatcher, nullptr) {}
InputMethodBase::InputMethodBase(
ImeKeyEventDispatcher* ime_key_event_dispatcher,
std::unique_ptr<VirtualKeyboardController> keyboard_controller)
: ime_key_event_dispatcher_(ime_key_event_dispatcher),
keyboard_controller_(std::move(keyboard_controller)) {}
InputMethodBase::~InputMethodBase() {
observer_list_.Notify(&InputMethodObserver::OnInputMethodDestroyed, this);
}
void InputMethodBase::SetImeKeyEventDispatcher(
ImeKeyEventDispatcher* ime_key_event_dispatcher) {
ime_key_event_dispatcher_ = ime_key_event_dispatcher;
}
void InputMethodBase::OnFocus() {
}
void InputMethodBase::OnBlur() {
}
void InputMethodBase::SetFocusedTextInputClient(TextInputClient* client) {
SetFocusedTextInputClientInternal(client);
}
void InputMethodBase::DetachTextInputClient(TextInputClient* client) {
if (text_input_client_ != client)
return;
SetFocusedTextInputClientInternal(nullptr);
}
TextInputClient* InputMethodBase::GetTextInputClient() const {
return text_input_client_;
}
void InputMethodBase::SetVirtualKeyboardBounds(const gfx::Rect& new_bounds) {
keyboard_bounds_ = new_bounds;
if (text_input_client_)
text_input_client_->EnsureCaretNotInRect(keyboard_bounds_);
}
void InputMethodBase::OnTextInputTypeChanged(TextInputClient* client) {
if (!IsTextInputClientFocused(client))
return;
NotifyTextInputStateChanged(client);
}
TextInputType InputMethodBase::GetTextInputType() const {
TextInputClient* client = GetTextInputClient();
return client
? (client->GetTextInputFlags() & TEXT_INPUT_FLAG_HAS_BEEN_PASSWORD
? TEXT_INPUT_TYPE_PASSWORD
: client->GetTextInputType())
: TEXT_INPUT_TYPE_NONE;
}
void InputMethodBase::SetVirtualKeyboardVisibilityIfEnabled(bool should_show) {
observer_list_.Notify(
&InputMethodObserver::OnVirtualKeyboardVisibilityChangedIfEnabled,
should_show);
auto* keyboard = GetVirtualKeyboardController();
if (keyboard) {
if (should_show) {
keyboard->DisplayVirtualKeyboard();
} else {
keyboard->DismissVirtualKeyboard();
}
}
}
void InputMethodBase::AddObserver(InputMethodObserver* observer) {
observer_list_.AddObserver(observer);
}
void InputMethodBase::RemoveObserver(InputMethodObserver* observer) {
observer_list_.RemoveObserver(observer);
}
VirtualKeyboardController* InputMethodBase::GetVirtualKeyboardController() {
return keyboard_controller_.get();
}
void InputMethodBase::SetVirtualKeyboardControllerForTesting(
std::unique_ptr<VirtualKeyboardController> controller) {
keyboard_controller_ = std::move(controller);
}
bool InputMethodBase::IsTextInputClientFocused(const TextInputClient* client) {
return client && (client == GetTextInputClient());
}
bool InputMethodBase::IsTextInputTypeNone() const {
return GetTextInputType() == TEXT_INPUT_TYPE_NONE;
}
void InputMethodBase::OnInputMethodChanged() const {
TextInputClient* client = GetTextInputClient();
if (!IsTextInputTypeNone())
client->OnInputMethodChanged();
}
ui::EventDispatchDetails InputMethodBase::DispatchKeyEventPostIME(
ui::KeyEvent* event) const {
if (text_input_client_) {
text_input_client_->OnDispatchingKeyEventPostIME(event);
if (event->handled())
return EventDispatchDetails();
}
return ime_key_event_dispatcher_
? ime_key_event_dispatcher_->DispatchKeyEventPostIME(event)
: ui::EventDispatchDetails();
}
void InputMethodBase::NotifyTextInputStateChanged(
const TextInputClient* client) {
observer_list_.Notify(&InputMethodObserver::OnTextInputStateChanged, client);
}
void InputMethodBase::NotifyTextInputCaretBoundsChanged(
const TextInputClient* client) {
observer_list_.Notify(&InputMethodObserver::OnCaretBoundsChanged, client);
}
void InputMethodBase::SetFocusedTextInputClientInternal(
TextInputClient* client) {
TextInputClient* old = text_input_client_;
if (old == client)
return;
OnWillChangeFocusedClient(old, client);
text_input_client_ = client; // nullptr allowed.
OnDidChangeFocusedClient(old, client);
NotifyTextInputStateChanged(text_input_client_);
// Move new focused window if necessary.
if (text_input_client_ && !keyboard_bounds_.IsEmpty())
text_input_client_->EnsureCaretNotInRect(keyboard_bounds_);
}
} // namespace ui