#ifndef UI_BASE_IME_ASH_INPUT_METHOD_ASH_H_
#define UI_BASE_IME_ASH_INPUT_METHOD_ASH_H_
#include <stdint.h>
#include <memory>
#include <optional>
#include <set>
#include <string_view>
#include "base/component_export.h"
#include "base/functional/callback.h"
#include "base/functional/callback_forward.h"
#include "base/memory/weak_ptr.h"
#include "ui/base/ime/ash/text_input_method.h"
#include "ui/base/ime/ash/text_input_target.h"
#include "ui/base/ime/ash/typing_session_manager.h"
#include "ui/base/ime/character_composer.h"
#include "ui/base/ime/composition_text.h"
#include "ui/base/ime/input_method_base.h"
#include "ui/base/ime/text_input_client.h"
#include "ui/events/event_dispatcher.h"
namespace ui::ime {
enum class KeyEventHandledState;
}
namespace ash {
class COMPONENT_EXPORT(UI_BASE_IME_ASH) InputMethodAsh
: public ui::InputMethodBase,
public TextInputTarget {
public:
explicit InputMethodAsh(ui::ImeKeyEventDispatcher* ime_key_event_dispatcher);
InputMethodAsh(const InputMethodAsh&) = delete;
InputMethodAsh& operator=(const InputMethodAsh&) = delete;
~InputMethodAsh() override;
ui::EventDispatchDetails DispatchKeyEvent(ui::KeyEvent* event) override;
void OnTextInputTypeChanged(ui::TextInputClient* client) override;
void OnCaretBoundsChanged(const ui::TextInputClient* client) override;
void CancelComposition(const ui::TextInputClient* client) override;
bool IsCandidatePopupOpen() const override;
ui::VirtualKeyboardController* GetVirtualKeyboardController() override;
void OnFocus() override;
void OnBlur() override;
void OnWillChangeFocusedClient(ui::TextInputClient* focused_before,
ui::TextInputClient* focused) override;
void OnDidChangeFocusedClient(ui::TextInputClient* focused_before,
ui::TextInputClient* focused) override;
void CommitText(
const std::u16string& text,
ui::TextInputClient::InsertTextCursorBehavior cursor_behavior) override;
bool SetCompositionRange(
uint32_t before,
uint32_t after,
const std::vector<ui::ImeTextSpan>& text_spans) override;
bool SetComposingRange(
uint32_t start,
uint32_t end,
const std::vector<ui::ImeTextSpan>& text_spans) override;
gfx::Range GetAutocorrectRange() override;
void SetAutocorrectRange(const gfx::Range& range,
SetAutocorrectRangeDoneCallback callback) override;
std::optional<ui::GrammarFragment> GetGrammarFragmentAtCursor() override;
bool ClearGrammarFragments(const gfx::Range& range) override;
bool AddGrammarFragments(
const std::vector<ui::GrammarFragment>& fragments) override;
void UpdateCompositionText(const ui::CompositionText& text,
uint32_t cursor_pos,
bool visible) override;
void DeleteSurroundingText(uint32_t num_char16s_before_cursor,
uint32_t num_char16s_after_cursor) override;
void ReplaceSurroundingText(uint32_t length_before_selection,
uint32_t length_after_selection,
std::u16string_view replacement_text) override;
SurroundingTextInfo GetSurroundingTextInfo() override;
void SendKeyEvent(ui::KeyEvent* event) override;
ui::InputMethod* GetInputMethod() override;
void ConfirmComposition(bool reset_engine) override;
bool HasCompositionText() override;
ukm::SourceId GetClientSourceForMetrics() override;
protected:
ui::CompositionText ExtractCompositionText(const ui::CompositionText& text,
uint32_t cursor_position) const;
[[nodiscard]] virtual ui::EventDispatchDetails ProcessKeyEventPostIME(
ui::KeyEvent* event,
ui::ime::KeyEventHandledState handled_state,
bool stopped_propagation);
void ResetContext(bool reset_engine = true);
private:
friend class TestableInputMethodAsh;
struct PendingSetCompositionRange {
PendingSetCompositionRange(const gfx::Range& range,
const std::vector<ui::ImeTextSpan>& text_spans);
PendingSetCompositionRange(const PendingSetCompositionRange& other);
~PendingSetCompositionRange();
gfx::Range range;
std::vector<ui::ImeTextSpan> text_spans;
};
struct PendingCommit {
std::u16string text;
size_t cursor = 0;
};
struct PendingAutocorrectRange {
PendingAutocorrectRange(const gfx::Range& range,
SetAutocorrectRangeDoneCallback callback);
~PendingAutocorrectRange();
gfx::Range range;
SetAutocorrectRangeDoneCallback callback;
};
void UpdateContextFocusState();
[[nodiscard]] ui::EventDispatchDetails ProcessFilteredKeyPressEvent(
ui::KeyEvent* event,
bool only_dispatch_vkey_processkey);
[[nodiscard]] ui::EventDispatchDetails ProcessUnfilteredKeyPressEvent(
ui::KeyEvent* event);
void MaybeProcessPendingInputMethodResult(ui::KeyEvent* event, bool filtered);
bool NeedInsertChar() const;
bool HasInputMethodResult() const;
bool ExecuteCharacterComposer(const ui::KeyEvent& event);
void HidePreeditText();
TextInputMethod::InputContext GetInputContext() const;
void ProcessKeyEventDone(ui::KeyEvent* event,
ui::ime::KeyEventHandledState handled_state);
bool IsPasswordOrNoneInputFieldFocused();
bool SendFakeProcessKeyEvent(bool pressed) const;
std::optional<ui::CompositionText> pending_composition_;
std::optional<PendingCommit> pending_commit_;
std::u16string previous_surrounding_text_;
gfx::Range previous_selection_range_;
bool composing_text_ = false;
bool composition_changed_ = false;
std::optional<PendingSetCompositionRange> pending_composition_range_;
std::unique_ptr<PendingAutocorrectRange> pending_autocorrect_range_;
ui::CharacterComposer character_composer_;
bool handling_key_event_ = false;
TypingSessionManager typing_session_manager_;
std::optional<ui::EventDispatchDetails> dispatch_details_;
GURL focused_url_;
base::WeakPtrFactory<InputMethodAsh> weak_ptr_factory_{this};
};
}
#endif