File: text_input.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (353 lines) | stat: -rw-r--r-- 14,983 bytes parent folder | download | duplicates (8)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef COMPONENTS_EXO_TEXT_INPUT_H_
#define COMPONENTS_EXO_TEXT_INPUT_H_

#include <optional>
#include <string>
#include <string_view>

#include "base/i18n/rtl.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_observation.h"
#include "components/exo/seat_observer.h"
#include "ui/base/ime/ash/input_method_manager.h"
#include "ui/base/ime/autocorrect_info.h"
#include "ui/base/ime/composition_text.h"
#include "ui/base/ime/surrounding_text_tracker.h"
#include "ui/base/ime/text_input_client.h"
#include "ui/base/ime/text_input_flags.h"
#include "ui/base/ime/text_input_mode.h"
#include "ui/base/ime/text_input_type.h"
#include "ui/base/ime/virtual_keyboard_controller.h"
#include "ui/base/ime/virtual_keyboard_controller_observer.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/range/range.h"

namespace ui {
class InputMethod;
}  // namespace ui

namespace exo {
class Surface;
class Seat;

// This class bridges the ChromeOS input method and a text-input context.
// It can be inactive, active, or in a pending state where Activate() was
// called but the associated window is not focused.
class TextInput : public ui::TextInputClient,
                  public ui::VirtualKeyboardControllerObserver,
                  public ash::input_method::InputMethodManager::Observer,
                  public SeatObserver {
 public:
  class Delegate {
   public:
    virtual ~Delegate() = default;

    // Called when the text input session is activated.
    virtual void Activated() = 0;

    // Called when the text input session is deactivated. TextInput does not
    // refer to the delegate anymore.
    virtual void Deactivated() = 0;

    // Called when the virtual keyboard visibility state has changed.
    virtual void OnVirtualKeyboardVisibilityChanged(bool is_visible) = 0;

    // Called when the virtual keyboard's occluded bounds has changed.
    // The bounds are in screen DIP.
    virtual void OnVirtualKeyboardOccludedBoundsChanged(
        const gfx::Rect& screen_bounds) = 0;

    // Returns true if the server can expect a finalize_virtual_keyboard_changes
    // request from the client.
    virtual bool SupportsFinalizeVirtualKeyboardChanges() = 0;

    // Set the 'composition text' of the current text input.
    virtual void SetCompositionText(const ui::CompositionText& composition) = 0;

    // Commit |text| to the current text input session.
    virtual void Commit(std::u16string_view text) = 0;

    // Set the cursor position.
    // |surrounding_text| is the current surrounding text.
    // The |selection| range is in UTF-16 offsets of the current surrounding
    // text. |selection| must be a valid range, i.e.
    // selection.IsValid() && selection.GetMax() <= surrounding_text.length().
    virtual void SetCursor(std::u16string_view surrounding_text,
                           const gfx::Range& selection) = 0;

    // Delete the surrounding text of the current text input.
    // |surrounding_text| is the current surrounding text.
    // The delete |range| is in UTF-16 offsets of the current surrounding text.
    // |range| must be a valid range, i.e.
    // range.IsValid() && range.GetMax() <= surrounding_text.length().
    virtual void DeleteSurroundingText(std::u16string_view surrounding_text,
                                       const gfx::Range& range) = 0;

    // Sends a key event.
    virtual void SendKey(const ui::KeyEvent& event) = 0;

    // Called when the text direction has changed.
    virtual void OnTextDirectionChanged(
        base::i18n::TextDirection direction) = 0;

    // Sets composition from the current surrounding text offsets.
    // Offsets in |cursor| and |range| is relative to the beginning of
    // |surrounding_text|. Offsets in |ui_ime_text_spans| is relative to the new
    // composition, i.e. relative to |range|'s start. All offsets are in UTF16,
    // and must be valid.
    virtual void SetCompositionFromExistingText(
        std::u16string_view surrounding_text,
        const gfx::Range& cursor,
        const gfx::Range& range,
        const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) = 0;

    // Clears all the grammar fragments in |range|.
    // |surrounding_text| is the current surrounding text, used for utf16 to
    // utf8 conversion.
    virtual void ClearGrammarFragments(std::u16string_view surrounding_text,
                                       const gfx::Range& range) = 0;

    // Adds a new grammar marker according to |fragments|. Clients should show
    // some visual indications such as underlining.
    // |surrounding_text| is the current surrounding text, used for utf16 to
    // utf8 conversion.
    virtual void AddGrammarFragment(std::u16string_view surrounding_text,
                                    const ui::GrammarFragment& fragment) = 0;

    // Sets the autocorrect range from the current surrounding text offsets.
    // Offsets in |range| is relative to the beginning of
    // |surrounding_text|. All offsets are in UTF16, and must be valid.
    virtual void SetAutocorrectRange(std::u16string_view surrounding_text,
                                     const gfx::Range& range) = 0;

    // Commits the current composition text.
    // If `keep_selection` is true, keep the selection range unchanged.
    // Otherwise, set the selection range to be after the committed text.
    // Returns whether the operation is supported by the client.
    virtual bool ConfirmComposition(bool keep_selection) = 0;

    // Does the current delegate support the new ConfirmComposition wayland
    // method name confirm_preedit?
    virtual bool SupportsConfirmPreedit() = 0;

    // Checks if InsertImage() is supported via wayland.
    virtual bool HasImageInsertSupport() = 0;

    // Inserts image.
    virtual void InsertImage(const GURL& src) = 0;
  };

  explicit TextInput(std::unique_ptr<Delegate> delegate);
  TextInput(const TextInput&) = delete;
  TextInput& operator=(const TextInput&) = delete;
  ~TextInput() override;

  // Request to activate the text input context on the surface. Activation will
  // occur immediately if the associated window is already focused, or
  // otherwise when the window gains focus.
  void Activate(Seat* seat,
                Surface* surface,
                ui::TextInputClient::FocusReason reason);

  // Deactivates the text input context.
  void Deactivate();

  // Shows the virtual keyboard if needed.
  void ShowVirtualKeyboardIfEnabled();

  // Hides the virtual keyboard.
  void HideVirtualKeyboard();

  // Re-synchronize the current status when the surrounding text has changed
  // during the text input session.
  void Resync();

  // Resets the current input method composition state.
  void Reset();

  // Sets the surrounding text in the app.
  // Ranges of |cursor_pos|, |grammar_fragment| and |autocorrect_info| are
  // relative to |text|.
  // |grammar_fragment| is the grammar fragment at the cursor position,
  // if given.
  // |autocorrect_info->bounds| is the bounding rect around the autocorrected
  // text and is relative to the window origin.
  void SetSurroundingText(
      std::u16string_view text,
      uint32_t offset,
      const gfx::Range& cursor_pos,
      const std::optional<ui::GrammarFragment>& grammar_fragment,
      const std::optional<ui::AutocorrectInfo>& autocorrect_info);

  // Sets the text input type, mode, flags, |should_do_learning|,
  // |can_compose_inline| and |surrounding_text_supported|.
  void SetTypeModeFlags(ui::TextInputType type,
                        ui::TextInputMode mode,
                        int flags,
                        bool should_do_learning,
                        bool can_compose_inline,
                        bool surrounding_text_supported);

  // Sets the bounds of the text caret, relative to the window origin.
  void SetCaretBounds(const gfx::Rect& bounds);

  // Finalizes pending virtual keyboard requested changes.
  void FinalizeVirtualKeyboardChanges();

  Delegate* delegate() { return delegate_.get(); }

  // ui::TextInputClient:
  base::WeakPtr<ui::TextInputClient> AsWeakPtr() override;
  void SetCompositionText(const ui::CompositionText& composition) override;
  size_t ConfirmCompositionText(bool keep_selection) override;
  void ClearCompositionText() override;
  void InsertText(const std::u16string& text,
                  InsertTextCursorBehavior cursor_behavior) override;
  void InsertChar(const ui::KeyEvent& event) override;
  bool CanInsertImage() override;
  void InsertImage(const GURL& src) override;
  ui::TextInputType GetTextInputType() const override;
  ui::TextInputMode GetTextInputMode() const override;
  base::i18n::TextDirection GetTextDirection() const override;
  int GetTextInputFlags() const override;
  bool CanComposeInline() const override;
  gfx::Rect GetCaretBounds() const override;
  gfx::Rect GetSelectionBoundingBox() const override;
  bool GetCompositionCharacterBounds(size_t index,
                                     gfx::Rect* rect) const override;
  bool HasCompositionText() const override;
  ui::TextInputClient::FocusReason GetFocusReason() const override;
  bool GetTextRange(gfx::Range* range) const override;
  bool GetCompositionTextRange(gfx::Range* range) const override;
  bool GetEditableSelectionRange(gfx::Range* range) const override;
  bool SetEditableSelectionRange(const gfx::Range& range) override;
  bool GetTextFromRange(const gfx::Range& range,
                        std::u16string* text) const override;
  void OnInputMethodChanged() override;
  bool ChangeTextDirectionAndLayoutAlignment(
      base::i18n::TextDirection direction) override;
  void ExtendSelectionAndDelete(size_t before, size_t after) override;
  void ExtendSelectionAndReplace(size_t before,
                                 size_t after,
                                 std::u16string_view replacement_text) override;
  void EnsureCaretNotInRect(const gfx::Rect& rect) override;
  bool IsTextEditCommandEnabled(ui::TextEditCommand command) const override;
  void SetTextEditCommandForNextKeyEvent(ui::TextEditCommand command) override;
  ukm::SourceId GetClientSourceForMetrics() const override;
  bool ShouldDoLearning() override;
  bool SetCompositionFromExistingText(
      const gfx::Range& range,
      const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) override;
  gfx::Range GetAutocorrectRange() const override;
  gfx::Rect GetAutocorrectCharacterBounds() const override;
  bool SetAutocorrectRange(const gfx::Range& range) override;
  std::optional<ui::GrammarFragment> GetGrammarFragmentAtCursor()
      const override;
  bool ClearGrammarFragments(const gfx::Range& range) override;
  bool AddGrammarFragments(
      const std::vector<ui::GrammarFragment>& fragments) override;
  bool SupportsAlwaysConfirmComposition() override;
  void GetActiveTextInputControlLayoutBounds(
      std::optional<gfx::Rect>* control_bounds,
      std::optional<gfx::Rect>* selection_bounds) override {}

  // ui::VirtualKeyboardControllerObserver:
  void OnKeyboardVisible(const gfx::Rect& keyboard_rect) override;
  void OnKeyboardHidden() override;

  // ash::input_method::InputMethodManager::Observer:
  void InputMethodChanged(ash::input_method::InputMethodManager* manager,
                          Profile* profile,
                          bool show_message) override;

  // SeatObserver:
  void OnSurfaceFocused(Surface* gained_focus,
                        Surface* lost_focus,
                        bool has_focused_surface) override;

 private:
  void AttachInputMethod();
  void DetachInputMethod();
  void ResetCompositionTextCache();

  bool ShouldStageVKState();
  void SendStagedVKVisibility();
  void SendStagedVKOccludedBounds();

  // Delegate to talk to actual its client.
  std::unique_ptr<Delegate> delegate_;

  // On requesting to show Virtual Keyboard, InputMethod may not be connected.
  // So, remember the request temporarily, and then on InputMethod connection
  // show the Virtual Keyboard.
  bool pending_vk_visible_ = false;

  // |surface_| and |seat_| are non-null if and only if the TextInput is in a
  // pending or active state, in which case the TextInput will be observing the
  // Seat.
  raw_ptr<Surface, DanglingUntriaged> surface_ = nullptr;
  raw_ptr<Seat, DanglingUntriaged> seat_ = nullptr;

  // If the TextInput is active (associated window has focus) and the
  // InputMethod is available, this is set and the TextInput will be its
  // focused client. Otherwise, it is null and the TextInput is not attached
  // to any InputMethod, so the TextInputClient overrides will not be called.
  raw_ptr<ui::InputMethod, DanglingUntriaged> input_method_ = nullptr;

  base::ScopedObservation<ash::input_method::InputMethodManager,
                          ash::input_method::InputMethodManager::Observer>
      input_method_manager_observation_{this};

  base::ScopedObservation<ui::VirtualKeyboardController,
                          ui::VirtualKeyboardControllerObserver>
      virtual_keyboard_observation_{this};

  // Cache of the current caret bounding box, sent from the client.
  gfx::Rect caret_bounds_;

  // Cache of the current input field attributes sent from the client.
  ui::TextInputType input_type_ = ui::TEXT_INPUT_TYPE_NONE;
  ui::TextInputMode input_mode_ = ui::TEXT_INPUT_MODE_DEFAULT;
  int flags_ = ui::TEXT_INPUT_FLAG_NONE;
  bool should_do_learning_ = true;
  bool can_compose_inline_ = true;
  ui::TextInputClient::FocusReason focus_reason_ =
      ui::TextInputClient::FOCUS_REASON_NONE;

  // Whether the client supports surrounding text.
  bool surrounding_text_supported_ = true;
  // If surrounding text is not supported and the active IME needs it, we force
  // using TEXT_INPUT_TYPE_NULL.
  bool use_null_input_type_ = false;

  // Tracks the surrounding text.
  ui::SurroundingTextTracker surrounding_text_tracker_;

  // Cache of the current text input direction, update from the Chrome OS IME.
  base::i18n::TextDirection direction_ = base::i18n::UNKNOWN_DIRECTION;

  // Cache of the grammar fragment at cursor position, send from Lacros side.
  std::optional<ui::GrammarFragment> grammar_fragment_at_cursor_;

  // Latest autocorrect information that was sent from the Wayland client.
  // along with the last surrounding text change.
  ui::AutocorrectInfo autocorrect_info_;

  // True when client has made virtual keyboard related requests but haven't
  // sent the virtual keyboard finalize request.
  bool pending_vk_finalize_ = false;
  // Holds the vk visibility to send to the client.
  std::optional<bool> staged_vk_visible_;
  // Holds the vk occluded bounds to send to the client.
  std::optional<gfx::Rect> staged_vk_occluded_bounds_;
  base::WeakPtrFactory<TextInput> weak_ptr_factory_{this};
};

}  // namespace exo

#endif  // COMPONENTS_EXO_TEXT_INPUT_H_