Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(89)

Side by Side Diff: ui/base/ime/remote_input_method_win.cc

Issue 67503004: Introduce RemoteInputMethodWin (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Revise comments, rename OnLanguageChanged to OnInputSourceChanged Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ui/base/ime/remote_input_method_win.h ('k') | ui/base/ime/remote_input_method_win_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2013 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 #include "ui/base/ime/remote_input_method_win.h"
6
7 #include "base/strings/utf_string_conversions.h"
8 #include "ui/base/ime/input_method.h"
9 #include "ui/base/ime/input_method_delegate.h"
10 #include "ui/base/ime/remote_input_method_delegate_win.h"
11 #include "ui/base/ime/text_input_client.h"
12 #include "ui/base/ime/win/tsf_input_scope.h"
13 #include "ui/events/event.h"
14 #include "ui/events/event_utils.h"
15 #include "ui/gfx/rect.h"
16
17 namespace ui {
18 namespace {
19
20 const LANGID kFallbackLangID =
21 MAKELANGID(LANG_NEUTRAL, SUBLANG_UI_CUSTOM_DEFAULT);
22
23 InputMethod* g_public_interface_ = NULL;
24 RemoteInputMethodPrivateWin* g_private_interface_ = NULL;
25
26 void RegisterInstance(InputMethod* public_interface,
27 RemoteInputMethodPrivateWin* private_interface) {
28 CHECK(g_public_interface_ == NULL)
29 << "Only one instance is supported at the same time";
30 CHECK(g_private_interface_ == NULL)
31 << "Only one instance is supported at the same time";
32 g_public_interface_ = public_interface;
33 g_private_interface_ = private_interface;
34 }
35
36 RemoteInputMethodPrivateWin* GetPrivate(InputMethod* public_interface) {
37 if (g_public_interface_ != public_interface)
38 return NULL;
39 return g_private_interface_;
40 }
41
42 void UnregisterInstance(InputMethod* public_interface) {
43 RemoteInputMethodPrivateWin* private_interface = GetPrivate(public_interface);
44 if (g_public_interface_ == public_interface &&
45 g_private_interface_ == private_interface) {
46 g_public_interface_ = NULL;
47 g_private_interface_ = NULL;
48 }
49 }
50
51 std::string GetLocaleString(LCID Locale_id, LCTYPE locale_type) {
52 wchar_t buffer[16] = {};
53
54 //|chars_written| includes NUL terminator.
55 const int chars_written =
56 GetLocaleInfo(Locale_id, locale_type, buffer, arraysize(buffer));
57 if (chars_written <= 1 || arraysize(buffer) < chars_written)
58 return std::string();
59 std::string result;
60 WideToUTF8(buffer, chars_written - 1, &result);
61 return result;
62 }
63
64 std::vector<int32> GetInputScopesAsInt(TextInputType text_input_type,
65 TextInputMode text_input_mode) {
66 std::vector<int32> result;
67 // An empty vector represents |text_input_type| is TEXT_INPUT_TYPE_NONE.
68 if (text_input_type == TEXT_INPUT_TYPE_NONE)
69 return result;
70
71 const std::vector<InputScope>& input_scopes =
72 tsf_inputscope::GetInputScopes(text_input_type, text_input_mode);
73 result.reserve(input_scopes.size());
74 for (size_t i = 0; i < input_scopes.size(); ++i)
75 result.push_back(static_cast<int32>(input_scopes[i]));
76 return result;
77 }
78
79 std::vector<gfx::Rect> GetCompositionCharacterBounds(
80 const TextInputClient* client) {
81 if (!client)
82 return std::vector<gfx::Rect>();
83
84 if (!client->HasCompositionText()) {
85 std::vector<gfx::Rect> caret;
86 caret.push_back(client->GetCaretBounds());
87 return caret;
88 }
89
90 std::vector<gfx::Rect> bounds;
91 for (uint32 i = 0;; ++i) {
92 gfx::Rect rect;
93 if (!client->GetCompositionCharacterBounds(i, &rect))
94 break;
95 bounds.push_back(rect);
96 }
97 return bounds;
98 }
99
100 class RemoteInputMethodWin : public InputMethod,
101 public RemoteInputMethodPrivateWin {
102 public:
103 explicit RemoteInputMethodWin(internal::InputMethodDelegate* delegate)
104 : delegate_(delegate),
105 remote_delegate_(NULL),
106 text_input_client_(NULL),
107 is_candidate_popup_open_(false),
108 is_ime_(false),
109 langid_(kFallbackLangID) {
110 RegisterInstance(this, this);
111 }
112
113 virtual ~RemoteInputMethodWin() {
114 UnregisterInstance(this);
115 }
116
117 private:
118 // Overridden from InputMethod:
119 virtual void SetDelegate(internal::InputMethodDelegate* delegate) OVERRIDE {
120 delegate_ = delegate;
121 }
122
123 virtual void Init(bool focused) OVERRIDE {}
124
125 virtual void OnFocus() OVERRIDE {}
126
127 virtual void OnBlur() OVERRIDE {}
128
129 virtual bool OnUntranslatedIMEMessage(const base::NativeEvent& event,
130 NativeEventResult* result) OVERRIDE {
131 return false;
132 }
133
134 virtual void SetFocusedTextInputClient(TextInputClient* client) OVERRIDE {
135 std::vector<int32> prev_input_scopes;
136 std::swap(input_scopes_, prev_input_scopes);
137 std::vector<gfx::Rect> prev_bounds;
138 std::swap(composition_character_bounds_, prev_bounds);
139 if (client) {
140 input_scopes_ = GetInputScopesAsInt(client->GetTextInputType(),
141 client->GetTextInputMode());
142 composition_character_bounds_ = GetCompositionCharacterBounds(client);
143 }
144
145 text_input_client_ = client;
146
147 if (!remote_delegate_ || (prev_input_scopes == input_scopes_ &&
148 prev_bounds == composition_character_bounds_))
149 return;
150 remote_delegate_->OnTextInputClientUpdated(input_scopes_,
151 composition_character_bounds_);
152 }
153
154 virtual void DetachTextInputClient(TextInputClient* client) OVERRIDE {
155 if (text_input_client_ != client)
156 return;
157 SetFocusedTextInputClient(NULL);
158 }
159
160 virtual TextInputClient* GetTextInputClient() const OVERRIDE {
161 return text_input_client_;
162 }
163
164 virtual bool DispatchKeyEvent(const ui::KeyEvent& event) OVERRIDE {
165 if (event.HasNativeEvent()) {
166 const base::NativeEvent& native_key_event = event.native_event();
167 if (native_key_event.message != WM_CHAR)
168 return false;
169 if (!text_input_client_)
170 return false;
171 text_input_client_->InsertChar(
172 static_cast<char16>(native_key_event.wParam),
173 ui::GetModifiersFromKeyState());
174 return true;
175 }
176
177 if (event.is_char()) {
178 if (text_input_client_) {
179 text_input_client_->InsertChar(event.key_code(),
180 ui::GetModifiersFromKeyState());
181 }
182 return true;
183 }
184 if (!delegate_)
185 return false;
186 return delegate_->DispatchFabricatedKeyEventPostIME(event.type(),
187 event.key_code(),
188 event.flags());
189 }
190
191 virtual void OnTextInputTypeChanged(const TextInputClient* client) OVERRIDE {
192 if (!text_input_client_ || text_input_client_ != client)
193 return;
194 std::vector<int32> prev_input_scopes;
195 std::swap(input_scopes_, prev_input_scopes);
196 input_scopes_ = GetInputScopesAsInt(client->GetTextInputType(),
197 client->GetTextInputMode());
198 if (input_scopes_ != prev_input_scopes && remote_delegate_) {
199 remote_delegate_->OnTextInputClientUpdated(
200 input_scopes_, composition_character_bounds_);
201 }
202 }
203
204 virtual void OnCaretBoundsChanged(const TextInputClient* client) OVERRIDE {
205 if (!text_input_client_ || text_input_client_ != client)
206 return;
207 std::vector<gfx::Rect> prev_rects;
208 std::swap(composition_character_bounds_, prev_rects);
209 composition_character_bounds_ = GetCompositionCharacterBounds(client);
210 if (composition_character_bounds_ != prev_rects && remote_delegate_) {
211 remote_delegate_->OnTextInputClientUpdated(
212 input_scopes_, composition_character_bounds_);
213 }
214 }
215
216 virtual void CancelComposition(const TextInputClient* client) OVERRIDE {
217 if (CanSendRemoteNotification(client))
218 remote_delegate_->CancelComposition();
219 }
220
221 virtual void OnInputLocaleChanged() OVERRIDE {
222 // not supported.
223 }
224
225 virtual std::string GetInputLocale() OVERRIDE {
226 const LCID locale_id = MAKELCID(langid_, SORT_DEFAULT);
227 std::string language =
228 GetLocaleString(locale_id, LOCALE_SISO639LANGNAME);
229 if (SUBLANGID(langid_) == SUBLANG_NEUTRAL || language.empty())
230 return language;
231 const std::string& region =
232 GetLocaleString(locale_id, LOCALE_SISO3166CTRYNAME);
233 if (region.empty())
234 return language;
235 return language.append(1, '-').append(region);
236 }
237
238 virtual base::i18n::TextDirection GetInputTextDirection() OVERRIDE {
239 switch (PRIMARYLANGID(langid_)) {
240 case LANG_ARABIC:
241 case LANG_HEBREW:
242 case LANG_PERSIAN:
243 case LANG_SYRIAC:
244 case LANG_UIGHUR:
245 case LANG_URDU:
246 return base::i18n::RIGHT_TO_LEFT;
247 default:
248 return base::i18n::LEFT_TO_RIGHT;
249 }
250 }
251
252 virtual bool IsActive() OVERRIDE {
253 return true; // always turned on
254 }
255
256 virtual TextInputType GetTextInputType() const OVERRIDE {
257 return text_input_client_ ? text_input_client_->GetTextInputType()
258 : TEXT_INPUT_TYPE_NONE;
259 }
260
261 virtual TextInputMode GetTextInputMode() const OVERRIDE {
262 return text_input_client_ ? text_input_client_->GetTextInputMode()
263 : TEXT_INPUT_MODE_DEFAULT;
264 }
265
266 virtual bool CanComposeInline() const OVERRIDE {
267 return text_input_client_ ? text_input_client_->CanComposeInline() : true;
268 }
269
270 virtual bool IsCandidatePopupOpen() const OVERRIDE {
271 return is_candidate_popup_open_;
272 }
273
274 virtual void AddObserver(InputMethodObserver* observer) OVERRIDE {
275 // not supported.
276 NOTREACHED();
277 }
278
279 virtual void RemoveObserver(InputMethodObserver* observer) OVERRIDE {
280 // not supported.
281 NOTREACHED();
282 }
283
284 // Overridden from RemoteInputMethodPrivateWin:
285 virtual void SetRemoteDelegate(
286 internal::RemoteInputMethodDelegateWin* delegate) OVERRIDE{
287 remote_delegate_ = delegate;
288
289 // Sync initial state.
290 if (remote_delegate_) {
291 remote_delegate_->OnTextInputClientUpdated(
292 input_scopes_, composition_character_bounds_);
293 }
294 }
295
296 virtual void OnCandidatePopupChanged(bool visible) OVERRIDE {
297 is_candidate_popup_open_ = visible;
298 }
299
300 virtual void OnInputSourceChanged(LANGID langid, bool /*is_ime*/) OVERRIDE {
301 // Note: Currently |is_ime| is not utilized yet.
302 const bool changed = (langid_ != langid);
303 langid_ = langid;
304 if (changed && GetTextInputClient())
305 GetTextInputClient()->OnInputMethodChanged();
306 }
307
308 bool CanSendRemoteNotification(
309 const TextInputClient* text_input_client) const {
310 return text_input_client_ &&
311 text_input_client_ == text_input_client &&
312 remote_delegate_;
313 }
314
315 internal::InputMethodDelegate* delegate_;
316 internal::RemoteInputMethodDelegateWin* remote_delegate_;
317
318 TextInputClient* text_input_client_;
319 std::vector<int32> input_scopes_;
320 std::vector<gfx::Rect> composition_character_bounds_;
321 bool is_candidate_popup_open_;
322 bool is_ime_;
323 LANGID langid_;
324
325 DISALLOW_COPY_AND_ASSIGN(RemoteInputMethodWin);
326 };
327
328 } // namespace
329
330 RemoteInputMethodPrivateWin::RemoteInputMethodPrivateWin() {}
331
332 // static
333 scoped_ptr<InputMethod> CreateRemoteInputMethodWin(
334 internal::InputMethodDelegate* delegate) {
335 return scoped_ptr<InputMethod>(new RemoteInputMethodWin(delegate));
336 }
337
338 // static
339 RemoteInputMethodPrivateWin* RemoteInputMethodPrivateWin::Get(
340 InputMethod* input_method) {
341 return GetPrivate(input_method);
342 }
343
344 } // namespace ui
OLDNEW
« no previous file with comments | « ui/base/ime/remote_input_method_win.h ('k') | ui/base/ime/remote_input_method_win_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698