File: surrounding_text_tracker.h

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (129 lines) | stat: -rw-r--r-- 4,858 bytes parent folder | download | duplicates (4)
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
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef UI_BASE_IME_SURROUNDING_TEXT_TRACKER_H_
#define UI_BASE_IME_SURROUNDING_TEXT_TRACKER_H_

#include <deque>
#include <string>
#include <string_view>
#include <variant>

#include "base/component_export.h"
#include "base/functional/callback.h"
#include "ui/base/ime/text_input_client.h"
#include "ui/gfx/range/range.h"

namespace ui {

struct CompositionText;

// Tracks the surrounding text. Because IMF works in an asynchronous manner,
// there will be timing gap that IM-Engine sends some request to the text input
// client, and the commit is actually notified.
// This class gives it a try to fill the gap by caching and emulating the
// latest surrounding text under the assumption that text editing requests are
// processed in a common manner.
class COMPONENT_EXPORT(UI_BASE_IME) SurroundingTextTracker {
 public:
  struct COMPONENT_EXPORT(UI_BASE_IME) State {
    // Returns the range of the surrounding text in UTF-16.
    gfx::Range GetSurroundingTextRange() const;

    // Returns the string piece of the composition range of the
    // |surrounding_text|.
    // If composition is out of the range, nullopt will be returned.
    std::optional<std::u16string_view> GetCompositionText() const;

    // Whole surrounding text, specifically this may include composition text.
    std::u16string surrounding_text;

    // Offset of the surrounding_text within the text input client.
    // This does not affect to either selection nor composition.
    size_t utf16_offset;

    // Selection range. If it is empty, it means the cursor. Must not be
    // InvalidRange. Must be fit in |surrounding_text| range.
    gfx::Range selection;

    // Composition range if it has. Maybe empty if there's no composition text.
    // Must not be InvalidRange. Must be fit in |surrounding_text| range.
    gfx::Range composition;
  };

  // The initial state is no-surrounding text, cursor at 0, and no composition.
  SurroundingTextTracker();
  SurroundingTextTracker(const SurroundingTextTracker&) = delete;
  SurroundingTextTracker& operator=(const SurroundingTextTracker&) = delete;
  ~SurroundingTextTracker();

  const State& predicted_state() const { return predicted_state_; }

  // Resets the internal state, including composition state, surrounding text
  // and held histories. Used when the entire state needs to be reset.
  // TODO(b/267944900): Investigate if this is still needed once
  // kWaylandCancelComposition flag is enabled by default.
  void Reset();

  // Resets only the composition state and held histories.
  // Used when only the composition state is cancelled by the input field.
  void CancelComposition();

  enum class UpdateResult {
    // Expected update entry is found in |expected_updates_|.
    kUpdated,
    // No update entry corresponding to the given arguments is found.
    // All the states are reset to the given arguments.
    kReset,
  };
  // Expected to be called on surrounding text update event from text input
  // client. If there was some known state matching to the arguments,
  // forgets the state histories before it, and returns kUpdateFoundInHistory.
  // Otherwise, forgets everything and reset by the state of the given
  // arguments, then returns kHistoryIsReset.
  // Note intentiontally ignored composition text.
  UpdateResult Update(const std::u16string_view surrounding_text,
                      size_t utf16_offset,
                      const gfx::Range& selection);

  // The following methods are used to guess new surrounding text state.
  // See TextInputClient for detailed behavior.
  void OnSetEditableSelectionRange(const gfx::Range& range);
  void OnSetCompositionText(const ui::CompositionText& composition);
  void OnSetCompositionFromExistingText(const gfx::Range& range);
  void OnConfirmCompositionText(bool keep_selection);
  void OnClearCompositionText();
  void OnInsertText(const std::u16string_view text,
                    TextInputClient::InsertTextCursorBehavior cursor_behavior);
  void OnExtendSelectionAndDelete(size_t before, size_t after);

 private:
  // History of events and their expected states.
  struct Entry {
    State state;
    base::RepeatingClosure command;

    Entry(State state, base::RepeatingClosure command);

    // Copy/Move-able.
    Entry(const Entry&);
    Entry(Entry&& entry);
    Entry& operator=(const Entry&);
    Entry& operator=(Entry&&);

    ~Entry();
  };

  void ResetInternal(std::u16string_view surrounding_text,
                     size_t utf16_offset,
                     const gfx::Range& selection);

  // The latest known state.
  State predicted_state_;
  std::deque<Entry> expected_updates_;
};

}  // namespace ui

#endif  // UI_BASE_IME_SURROUNDING_TEXT_TRACKER_H_