1 // Copyright 2018 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 #ifndef COMPONENTS_EXO_TEXT_INPUT_H_
6 #define COMPONENTS_EXO_TEXT_INPUT_H_
7 
8 #include "ash/public/cpp/keyboard/keyboard_controller_observer.h"
9 #include "base/optional.h"
10 #include "ui/base/ime/text_input_client.h"
11 #include "ui/base/ime/text_input_flags.h"
12 #include "ui/base/ime/text_input_mode.h"
13 #include "ui/base/ime/text_input_type.h"
14 #include "ui/gfx/geometry/rect.h"
15 
16 namespace ui {
17 class InputMethod;
18 }
19 
20 namespace keyboard {
21 class KeyboardUIController;
22 }
23 
24 namespace exo {
25 class Surface;
26 
27 size_t OffsetFromUTF8Offset(const base::StringPiece& text, uint32_t offset);
28 size_t OffsetFromUTF16Offset(const base::StringPiece16& text, uint32_t offset);
29 
30 // This class bridges the ChromeOS input method and a text-input context.
31 class TextInput : public ui::TextInputClient,
32                   public ash::KeyboardControllerObserver {
33  public:
34   class Delegate {
35    public:
36     virtual ~Delegate() = default;
37 
38     // Called when the text input session is activated.
39     virtual void Activated() = 0;
40 
41     // Called when the text input session is deactivated. TextInput does not
42     // refer to the delegate anymore.
43     virtual void Deactivated() = 0;
44 
45     // Called when the virtual keyboard visibility state has changed.
46     virtual void OnVirtualKeyboardVisibilityChanged(bool is_visible) = 0;
47 
48     // Set the 'composition text' of the current text input.
49     virtual void SetCompositionText(const ui::CompositionText& composition) = 0;
50 
51     // Commit |text| to the current text input session.
52     virtual void Commit(const base::string16& text) = 0;
53 
54     // Set the cursor position. The range should be in bytes offset.
55     virtual void SetCursor(const gfx::Range& selection) = 0;
56 
57     // Delete the surrounding text of the current text input. The range should
58     // be in the bytes offset.
59     virtual void DeleteSurroundingText(const gfx::Range& range) = 0;
60 
61     // Sends a key event.
62     virtual void SendKey(const ui::KeyEvent& event) = 0;
63 
64     // Called when the text direction has changed.
65     virtual void OnTextDirectionChanged(
66         base::i18n::TextDirection direction) = 0;
67   };
68 
69   TextInput(std::unique_ptr<Delegate> delegate);
70   ~TextInput() override;
71 
72   // Activates the text input context on the surface. Note that surface can be
73   // an app surface (hosted by a shell surface) or can be an independent one
74   // created by the text-input client.
75   void Activate(Surface* surface);
76 
77   // Deactivates the text input context.
78   void Deactivate();
79 
80   // Shows the virtual keyboard if needed.
81   void ShowVirtualKeyboardIfEnabled();
82 
83   // Hides the virtual keyboard.
84   void HideVirtualKeyboard();
85 
86   // Re-synchronize the current status when the surrounding text has changed
87   // during the text input session.
88   void Resync();
89 
90   // Sets the surrounding text in the app.
91   void SetSurroundingText(const base::string16& text,
92                           uint32_t cursor_pos,
93                           uint32_t anchor);
94 
95   // Sets the text input type, mode, flags, and |should_do_learning|.
96   void SetTypeModeFlags(ui::TextInputType type,
97                         ui::TextInputMode mode,
98                         int flags,
99                         bool should_do_learning);
100 
101   // Sets the bounds of the text caret, relative to the window origin.
102   void SetCaretBounds(const gfx::Rect& bounds);
103 
delegate()104   Delegate* delegate() { return delegate_.get(); }
105 
106   // ui::TextInputClient:
107   void SetCompositionText(const ui::CompositionText& composition) override;
108   void ConfirmCompositionText(bool keep_selection) override;
109   void ClearCompositionText() override;
110   void InsertText(const base::string16& text) override;
111   void InsertChar(const ui::KeyEvent& event) override;
112   ui::TextInputType GetTextInputType() const override;
113   ui::TextInputMode GetTextInputMode() const override;
114   base::i18n::TextDirection GetTextDirection() const override;
115   int GetTextInputFlags() const override;
116   bool CanComposeInline() const override;
117   gfx::Rect GetCaretBounds() const override;
118   bool GetCompositionCharacterBounds(uint32_t index,
119                                      gfx::Rect* rect) const override;
120   bool HasCompositionText() const override;
121   ui::TextInputClient::FocusReason GetFocusReason() const override;
122   bool GetTextRange(gfx::Range* range) const override;
123   bool GetCompositionTextRange(gfx::Range* range) const override;
124   bool GetEditableSelectionRange(gfx::Range* range) const override;
125   bool SetEditableSelectionRange(const gfx::Range& range) override;
126   bool DeleteRange(const gfx::Range& range) override;
127   bool GetTextFromRange(const gfx::Range& range,
128                         base::string16* text) const override;
129   void OnInputMethodChanged() override;
130   bool ChangeTextDirectionAndLayoutAlignment(
131       base::i18n::TextDirection direction) override;
132   void ExtendSelectionAndDelete(size_t before, size_t after) override;
133   void EnsureCaretNotInRect(const gfx::Rect& rect) override;
134   bool IsTextEditCommandEnabled(ui::TextEditCommand command) const override;
135   void SetTextEditCommandForNextKeyEvent(ui::TextEditCommand command) override;
136   ukm::SourceId GetClientSourceForMetrics() const override;
137   bool ShouldDoLearning() override;
138   bool SetCompositionFromExistingText(
139       const gfx::Range& range,
140       const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) override;
141 
142   // ash::KeyboardControllerObserver:
143   void OnKeyboardVisibilityChanged(bool is_visible) override;
144 
145  private:
146   void AttachInputMethod();
147   void DetachInputMethod();
148 
149   std::unique_ptr<Delegate> delegate_;
150   keyboard::KeyboardUIController* keyboard_ui_controller_ = nullptr;
151 
152   bool pending_vk_visible_ = false;
153   aura::Window* window_ = nullptr;
154   ui::InputMethod* input_method_ = nullptr;
155   gfx::Rect caret_bounds_;
156   ui::TextInputType input_type_ = ui::TEXT_INPUT_TYPE_NONE;
157   ui::TextInputMode input_mode_ = ui::TEXT_INPUT_MODE_DEFAULT;
158   int flags_ = ui::TEXT_INPUT_FLAG_NONE;
159   bool should_do_learning_ = true;
160   ui::CompositionText composition_;
161   base::string16 surrounding_text_;
162   base::Optional<gfx::Range> cursor_pos_;
163   base::i18n::TextDirection direction_ = base::i18n::UNKNOWN_DIRECTION;
164 
165   DISALLOW_COPY_AND_ASSIGN(TextInput);
166 };
167 
168 }  // namespace exo
169 
170 #endif  // COMPONENTS_EXO_KEYBOARD_H_
171