blob: 797f2ee3b7e7af91df122257ea53dacd6eae6413 [file] [log] [blame]
ekaramadadd882292016-06-08 15:22:561// Copyright 2016 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 CONTENT_BROWSER_RENDERER_HOST_TEXT_INPUT_MANAGER_H__
6#define CONTENT_BROWSER_RENDERER_HOST_TEXT_INPUT_MANAGER_H__
7
8#include <unordered_map>
ekaramadfcce0882016-07-07 02:44:519#include <utility>
ekaramadadd882292016-06-08 15:22:5610
11#include "base/observer_list.h"
ekaramad6f1786b2016-07-21 21:10:5812#include "base/strings/string16.h"
ekaramadadd882292016-06-08 15:22:5613#include "content/common/content_export.h"
14#include "content/common/text_input_state.h"
ekaramadfcce0882016-07-07 02:44:5115#include "ui/gfx/geometry/rect.h"
ekaramad6f1786b2016-07-21 21:10:5816#include "ui/gfx/range/range.h"
ekaramadfcce0882016-07-07 02:44:5117#include "ui/gfx/selection_bound.h"
18
19struct ViewHostMsg_SelectionBounds_Params;
ekaramadadd882292016-06-08 15:22:5620
ekaramadadd882292016-06-08 15:22:5621namespace content {
ekaramadb8e23a96c2016-07-13 01:21:1522
ekaramad8cba78862016-06-24 19:42:3123class RenderWidgetHostImpl;
ekaramadadd882292016-06-08 15:22:5624class RenderWidgetHostViewBase;
ekaramadadd882292016-06-08 15:22:5625
26// A class which receives updates of TextInputState from multiple sources and
27// decides what the new TextInputState is. It also notifies the observers when
28// text input state is updated.
29class CONTENT_EXPORT TextInputManager {
30 public:
31 // The tab's top-level RWHV should be an observer of TextInputManager to get
32 // notifications about changes in TextInputState or other IME related state
33 // for child frames.
34 class CONTENT_EXPORT Observer {
35 public:
36 // Called when a view has called UpdateTextInputState on TextInputManager.
37 // If the call has led to a change in TextInputState, |did_update_state| is
38 // true. In some plaforms, we need this update even when the state has not
ekaramaddb49e172016-11-30 08:44:4039 // changed (e.g., Aura for updating IME). Also note that |updated_view| is
40 // the view which has most recently received an update in TextInputState.
41 // |updated_view| should not be used to obtain any IME state since this
42 // observer method might have been called in the process of unregistering
43 // |active_view_| from TextInputManager (which in turn is a result of either
44 // destroying |active_view_| or TextInputManager).
ekaramadadd882292016-06-08 15:22:5645 virtual void OnUpdateTextInputStateCalled(
46 TextInputManager* text_input_manager,
47 RenderWidgetHostViewBase* updated_view,
48 bool did_update_state) {}
ekaramad50ee2032016-06-29 02:18:2549 // Called when |updated_view| has called ImeCancelComposition on
50 // TextInputManager.
51 virtual void OnImeCancelComposition(
52 TextInputManager* text_input_manager,
53 RenderWidgetHostViewBase* updated_view) {}
ekaramadb8e23a96c2016-07-13 01:21:1554 // Called when |updated_view| has changed its SelectionRegion.
ekaramadfcce0882016-07-07 02:44:5155 virtual void OnSelectionBoundsChanged(
56 TextInputManager* text_input_manager,
57 RenderWidgetHostViewBase* updated_view) {}
ekaramadb8e23a96c2016-07-13 01:21:1558 // Called when |updated_view| has changed its CompositionRangeInfo.
59 virtual void OnImeCompositionRangeChanged(
60 TextInputManager* text_input_manager,
61 RenderWidgetHostViewBase* updated_view) {}
ekaramad6f1786b2016-07-21 21:10:5862 // Called when the text selection for the |updated_view_| has changed.
63 virtual void OnTextSelectionChanged(
64 TextInputManager* text_input_manager,
65 RenderWidgetHostViewBase* updated_view) {}
66 };
67
ekaramad2f520092016-08-22 23:10:2468 // Text selection bounds.
69 struct SelectionRegion {
70 SelectionRegion();
71 SelectionRegion(const SelectionRegion& other);
72
ekaramad2f520092016-08-22 23:10:2473 // The begining of the selection region.
74 gfx::SelectionBound anchor;
75 // The end of the selection region (caret position).
76 gfx::SelectionBound focus;
77
78 // The following variables are only used on Mac platform.
79 // The current caret bounds.
80 gfx::Rect caret_rect;
81 // The current first selection bounds.
82 gfx::Rect first_selection_rect;
83 };
84
85 // Composition range information.
86 struct CompositionRangeInfo {
87 CompositionRangeInfo();
88 CompositionRangeInfo(const CompositionRangeInfo& other);
89 ~CompositionRangeInfo();
90
91 std::vector<gfx::Rect> character_bounds;
92 gfx::Range range;
93 };
94
ekaramad374b2662017-03-02 20:44:5295 // This class is used to store text selection information for views. The text
96 // selection information includes a range around the selected (highlighted)
97 // text which is defined by an offset from the beginning of the page/frame,
98 // a range for the selection, and the text including the selection which
99 // might include several characters before and after it.
100 class TextSelection {
101 public:
ekaramad6f1786b2016-07-21 21:10:58102 TextSelection();
103 TextSelection(const TextSelection& other);
104 ~TextSelection();
105
ekaramad374b2662017-03-02 20:44:52106 void SetSelection(const base::string16& text,
107 size_t offset,
108 const gfx::Range& range);
ekaramad65cf5592016-08-18 21:44:53109
ekaramad374b2662017-03-02 20:44:52110 const base::string16& selected_text() const { return selected_text_; }
111 size_t offset() const { return offset_; }
112 const gfx::Range& range() const { return range_; }
113 const base::string16& text() const { return text_; }
114
115 private:
ekaramad6f1786b2016-07-21 21:10:58116 // The offset of the text stored in |text| relative to the start of the web
117 // page.
ekaramad374b2662017-03-02 20:44:52118 size_t offset_;
ekaramad6f1786b2016-07-21 21:10:58119
ekaramad374b2662017-03-02 20:44:52120 // The range of the selection in the page (highlighted text).
121 gfx::Range range_;
ekaramad6f1786b2016-07-21 21:10:58122
ekaramad374b2662017-03-02 20:44:52123 // The highlighted text which is the portion of |text_| marked by |offset_|
124 // and |range_|. It will be an empty string if either |text_| or |range_|
125 // are empty of this selection information is invalid (i.e., |range_| does
126 // not cover any of |text_|.
127 base::string16 selected_text_;
128
129 // Part of the text on the page which includes the highlighted text plus
130 // possibly several characters before and after it.
131 base::string16 text_;
ekaramadadd882292016-06-08 15:22:56132 };
133
134 TextInputManager();
135 ~TextInputManager();
136
ekaramad8cba78862016-06-24 19:42:31137 // Returns the currently active widget, i.e., the RWH which is associated with
138 // |active_view_|.
139 RenderWidgetHostImpl* GetActiveWidget() const;
ekaramadadd882292016-06-08 15:22:56140
ekaramadb8e23a96c2016-07-13 01:21:15141 // ---------------------------------------------------------------------------
142 // The following methods can be used to obtain information about IME-related
143 // state for the active RenderWidgetHost. If the active widget is nullptr, the
144 // methods below will return nullptr as well.
145 // Users of these methods should not hold on to the pointers as they become
146 // dangling if the TextInputManager or |active_view_| are destroyed.
147
ekaramaddb49e172016-11-30 08:44:40148 // Returns the currently stored TextInputState for |active_view_|. A state of
149 // nullptr can be interpreted as a ui::TextInputType of
150 // ui::TEXT_INPUT_TYPE_NONE.
151 const TextInputState* GetTextInputState() const;
ekaramadadd882292016-06-08 15:22:56152
ekaramad2f520092016-08-22 23:10:24153 // Returns the selection bounds information for |view|. If |view| == nullptr,
154 // it will return the corresponding information for |active_view_| or nullptr
155 // if there are no active views.
156 const SelectionRegion* GetSelectionRegion(
157 RenderWidgetHostViewBase* view = nullptr) const;
ekaramadfcce0882016-07-07 02:44:51158
ekaramadd773ff42016-08-12 19:30:40159 // Returns the composition range and character bounds information for the
ekaramad79819af02017-04-10 21:10:26160 // |active_view_|. Returns nullptr If |active_view_| == nullptr.
161 const TextInputManager::CompositionRangeInfo* GetCompositionRangeInfo() const;
ekaramadb8e23a96c2016-07-13 01:21:15162
ekaramad6f1786b2016-07-21 21:10:58163 // The following method returns the text selection state for the given |view|.
164 // If |view| == nullptr, it will assume |active_view_| and return its state.
165 // In the case of |active_view_| == nullptr, the method will return nullptr.
166 const TextSelection* GetTextSelection(
167 RenderWidgetHostViewBase* view = nullptr) const;
168
ekaramad8cba78862016-06-24 19:42:31169 // ---------------------------------------------------------------------------
170 // The following methods are called by RWHVs on the tab to update their IME-
171 // related state.
172
ekaramadadd882292016-06-08 15:22:56173 // Updates the TextInputState for |view|.
174 void UpdateTextInputState(RenderWidgetHostViewBase* view,
175 const TextInputState& state);
176
ekaramad50ee2032016-06-29 02:18:25177 // The current IME composition has been cancelled on the renderer side for
178 // the widget corresponding to |view|.
179 void ImeCancelComposition(RenderWidgetHostViewBase* view);
180
ekaramadfcce0882016-07-07 02:44:51181 // Updates the selection bounds for the |view|. In Aura, selection bounds are
182 // used to provide the InputMethod with the position of the caret, e.g., in
183 // setting the position of the ui::ImeWindow.
184 void SelectionBoundsChanged(RenderWidgetHostViewBase* view,
185 const ViewHostMsg_SelectionBounds_Params& params);
186
ekaramadb8e23a96c2016-07-13 01:21:15187 // Called when the composition range and/or character bounds have changed.
188 void ImeCompositionRangeChanged(
189 RenderWidgetHostViewBase* view,
190 const gfx::Range& range,
191 const std::vector<gfx::Rect>& character_bounds);
192
ekaramad6f1786b2016-07-21 21:10:58193 // Updates the new text selection information for the |view|.
194 void SelectionChanged(RenderWidgetHostViewBase* view,
195 const base::string16& text,
196 size_t offset,
197 const gfx::Range& range);
198
ekaramadadd882292016-06-08 15:22:56199 // Registers the given |view| for tracking its TextInputState. This is called
200 // by any view which has updates in its TextInputState (whether tab's RWHV or
201 // that of a child frame). The |view| must unregister itself before being
202 // destroyed (i.e., call TextInputManager::Unregister).
203 void Register(RenderWidgetHostViewBase* view);
204
205 // Clears the TextInputState from the |view|. If |view == active_view_|, this
206 // call will lead to a TextInputState update since the TextInputState.type
207 // should be reset to none.
208 void Unregister(RenderWidgetHostViewBase* view);
209
210 // Returns true if |view| is already registered.
211 bool IsRegistered(RenderWidgetHostViewBase* view) const;
212
213 // Add and remove observers for notifications regarding updates in the
214 // TextInputState. Clients must be sure to remove themselves before they go
215 // away.
216 // Only the tab's RWHV should observer TextInputManager. In tests, however,
217 // in addition to the tab's RWHV, one or more test observers might observe
218 // TextInputManager.
219 void AddObserver(Observer* observer);
220 void RemoveObserver(Observer* observer);
ekaramadfd5f5a892016-08-12 04:33:10221 bool HasObserver(Observer* observer) const;
ekaramadadd882292016-06-08 15:22:56222
ekaramad8cba78862016-06-24 19:42:31223 RenderWidgetHostViewBase* active_view_for_testing() { return active_view_; }
ekaramad936536d2016-06-29 05:44:44224 size_t GetRegisteredViewsCountForTesting();
225 ui::TextInputType GetTextInputTypeForViewForTesting(
226 RenderWidgetHostViewBase* view);
ekaramad8cba78862016-06-24 19:42:31227
ekaramadadd882292016-06-08 15:22:56228 private:
ekaramadfcce0882016-07-07 02:44:51229 // This class is used to create maps which hold specific IME state for a
230 // view.
231 template <class Value>
232 class ViewMap : public std::unordered_map<RenderWidgetHostViewBase*, Value> {
233 };
234
ekaramadadd882292016-06-08 15:22:56235 void NotifyObserversAboutInputStateUpdate(RenderWidgetHostViewBase* view,
236 bool did_update_state);
237
ekaramad8cba78862016-06-24 19:42:31238 // The view with active text input state, i.e., a focused <input> element.
239 // It will be nullptr if no such view exists. Note that the active view
240 // cannot have a |TextInputState.type| of ui::TEXT_INPUT_TYPE_NONE.
ekaramadadd882292016-06-08 15:22:56241 RenderWidgetHostViewBase* active_view_;
242
ekaramad4cfc03e2016-07-21 17:34:21243 // The following maps track corresponding IME state for views. For each view,
244 // the values in the map are initialized and cleared in Register and
245 // Unregister methods, respectively.
ekaramadfcce0882016-07-07 02:44:51246 ViewMap<TextInputState> text_input_state_map_;
ekaramadfcce0882016-07-07 02:44:51247 ViewMap<SelectionRegion> selection_region_map_;
ekaramadb8e23a96c2016-07-13 01:21:15248 ViewMap<CompositionRangeInfo> composition_range_info_map_;
ekaramad6f1786b2016-07-21 21:10:58249 ViewMap<TextSelection> text_selection_map_;
ekaramadadd882292016-06-08 15:22:56250
251 base::ObserverList<Observer> observer_list_;
252
253 DISALLOW_COPY_AND_ASSIGN(TextInputManager);
254};
255}
256
ekaramadb8e23a96c2016-07-13 01:21:15257#endif // CONTENT_BROWSER_RENDERER_HOST_TEXT_INPUT_MANAGER_H__