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

Side by Side Diff: views/ime/input_method_win.cc

Issue 8294026: Support IMM32 reconversion on Windows (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: update Created 9 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "views/ime/input_method_win.h" 5 #include "views/ime/input_method_win.h"
6 6
7 #include "base/basictypes.h" 7 #include "base/basictypes.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/string_util.h" 9 #include "base/string_util.h"
10 #include "ui/base/keycodes/keyboard_codes.h" 10 #include "ui/base/keycodes/keyboard_codes.h"
11 #include "views/events/event.h" 11 #include "views/events/event.h"
12 12
13 static const size_t kExtraNumberOfChars = 100;
James Su 2011/10/28 04:20:45 I think 10~20 should be enough. And how about to a
Peng 2011/10/28 15:42:19 Done.
14
13 namespace views { 15 namespace views {
14 16
15 InputMethodWin::InputMethodWin(internal::InputMethodDelegate* delegate) 17 InputMethodWin::InputMethodWin(internal::InputMethodDelegate* delegate)
16 : active_(false), 18 : active_(false),
17 direction_(base::i18n::UNKNOWN_DIRECTION), 19 direction_(base::i18n::UNKNOWN_DIRECTION),
18 pending_requested_direction_(base::i18n::UNKNOWN_DIRECTION) { 20 pending_requested_direction_(base::i18n::UNKNOWN_DIRECTION) {
19 set_delegate(delegate); 21 set_delegate(delegate);
20 } 22 }
21 23
22 InputMethodWin::~InputMethodWin() { 24 InputMethodWin::~InputMethodWin() {
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
108 break; 110 break;
109 case WM_IME_STARTCOMPOSITION: 111 case WM_IME_STARTCOMPOSITION:
110 result = OnImeStartComposition(message, w_param, l_param, handled); 112 result = OnImeStartComposition(message, w_param, l_param, handled);
111 break; 113 break;
112 case WM_IME_COMPOSITION: 114 case WM_IME_COMPOSITION:
113 result = OnImeComposition(message, w_param, l_param, handled); 115 result = OnImeComposition(message, w_param, l_param, handled);
114 break; 116 break;
115 case WM_IME_ENDCOMPOSITION: 117 case WM_IME_ENDCOMPOSITION:
116 result = OnImeEndComposition(message, w_param, l_param, handled); 118 result = OnImeEndComposition(message, w_param, l_param, handled);
117 break; 119 break;
120 case WM_IME_REQUEST:
121 result = OnImeRequest(message, w_param, l_param, handled);
122 break;
118 case WM_CHAR: 123 case WM_CHAR:
119 case WM_SYSCHAR: 124 case WM_SYSCHAR:
120 result = OnChar(message, w_param, l_param, handled); 125 result = OnChar(message, w_param, l_param, handled);
121 break; 126 break;
122 case WM_DEADCHAR: 127 case WM_DEADCHAR:
123 case WM_SYSDEADCHAR: 128 case WM_SYSDEADCHAR:
124 result = OnDeadChar(message, w_param, l_param, handled); 129 result = OnDeadChar(message, w_param, l_param, handled);
125 break; 130 break;
126 default: 131 default:
127 NOTREACHED() << "Unknown IME message:" << message; 132 NOTREACHED() << "Unknown IME message:" << message;
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
212 return 0; 217 return 0;
213 218
214 if (GetTextInputClient()->HasCompositionText()) 219 if (GetTextInputClient()->HasCompositionText())
215 GetTextInputClient()->ClearCompositionText(); 220 GetTextInputClient()->ClearCompositionText();
216 221
217 ime_input_.ResetComposition(hwnd()); 222 ime_input_.ResetComposition(hwnd());
218 ime_input_.DestroyImeWindow(hwnd()); 223 ime_input_.DestroyImeWindow(hwnd());
219 return 0; 224 return 0;
220 } 225 }
221 226
227 LRESULT InputMethodWin::OnImeRequest(
228 UINT message, WPARAM wparam, LPARAM lparam, BOOL* handled) {
229 *handled = FALSE;
230
231 // Should not receive WM_IME_REQUEST message, if IME is disabled.
232 const ui::TextInputType type = GetTextInputType();
233 if (type == ui::TEXT_INPUT_TYPE_NONE ||
234 type == ui::TEXT_INPUT_TYPE_PASSWORD) {
235 return 0;
236 }
237
238 switch (wparam) {
239 case IMR_RECONVERTSTRING:
240 *handled = TRUE;
241 return OnReconvertString(reinterpret_cast<RECONVERTSTRING*>(lparam));
242 case IMR_DOCUMENTFEED:
243 *handled = TRUE;
244 return OnDocumentFeed(reinterpret_cast<RECONVERTSTRING*>(lparam));
245 default:
246 return 0;
247 }
248 }
249
222 LRESULT InputMethodWin::OnChar( 250 LRESULT InputMethodWin::OnChar(
223 UINT message, WPARAM wparam, LPARAM lparam, BOOL* handled) { 251 UINT message, WPARAM wparam, LPARAM lparam, BOOL* handled) {
224 *handled = TRUE; 252 *handled = TRUE;
225 253
226 // We need to send character events to the focused text input client event if 254 // We need to send character events to the focused text input client event if
227 // its text input type is ui::TEXT_INPUT_TYPE_NONE. 255 // its text input type is ui::TEXT_INPUT_TYPE_NONE.
228 if (!GetTextInputClient()) 256 if (!GetTextInputClient())
229 return 0; 257 return 0;
230 258
231 int flags = 0; 259 int flags = 0;
(...skipping 15 matching lines...) Expand all
247 // what dead key was pressed. 275 // what dead key was pressed.
248 ui::CompositionText composition; 276 ui::CompositionText composition;
249 composition.text.assign(1, static_cast<char16>(wparam)); 277 composition.text.assign(1, static_cast<char16>(wparam));
250 composition.selection = ui::Range(0, 1); 278 composition.selection = ui::Range(0, 1);
251 composition.underlines.push_back( 279 composition.underlines.push_back(
252 ui::CompositionUnderline(0, 1, SK_ColorBLACK, false)); 280 ui::CompositionUnderline(0, 1, SK_ColorBLACK, false));
253 GetTextInputClient()->SetCompositionText(composition); 281 GetTextInputClient()->SetCompositionText(composition);
254 return 0; 282 return 0;
255 } 283 }
256 284
285 LRESULT InputMethodWin::OnDocumentFeed(RECONVERTSTRING *reconv) {
James Su 2011/10/28 04:20:45 Per our discussion, feel free to remove this metho
286 TextInputClient* client = GetTextInputClient();
287 if (!client)
288 return 0;
289
290 ui::Range text_range;
291 if (!client->GetTextRange(&text_range) || text_range.is_empty())
292 return 0;
293
294 bool result = false;
295 ui::Range target_range;
296 if (client->HasCompositionText())
297 result = client->GetCompositionTextRange(&target_range);
298
299 if (!result || target_range.is_empty()) {
300 if (!client->GetSelectionRange(&target_range) ||
301 !target_range.IsValid()) {
302 return 0;
303 }
304 }
305
306 if (!text_range.Contains(target_range))
307 return 0;
308
309 if (target_range.GetMin() - text_range.start() > kExtraNumberOfChars)
310 text_range.set_start(target_range.GetMin() - kExtraNumberOfChars);
311
312 if (text_range.end() - target_range.GetMax() > kExtraNumberOfChars)
313 text_range.set_end(target_range.GetMax() + kExtraNumberOfChars);
314
315 size_t len = text_range.length();
316 size_t need_size = sizeof(RECONVERTSTRING) + len * sizeof(WCHAR);
317
318 if (!reconv)
319 return need_size;
320
321 if (reconv->dwSize < need_size)
322 return 0;
323
324 string16 text;
325 if (!GetTextInputClient()->GetTextFromRange(text_range, &text))
326 return 0;
327
328 reconv->dwVersion = 0;
329 reconv->dwStrLen = len;
330 reconv->dwStrOffset = sizeof(RECONVERTSTRING);
331 reconv->dwCompStrLen =
332 client->HasCompositionText() ? target_range.length() : 0;
333 reconv->dwCompStrOffset =
334 (target_range.GetMin() - text_range.start()) * sizeof(WCHAR);
335 reconv->dwTargetStrLen = target_range.length();
336 reconv->dwTargetStrOffset = reconv->dwCompStrOffset;
337
338 memcpy((char*)reconv + sizeof(RECONVERTSTRING),
339 text.c_str(), len * sizeof(WCHAR));
340
341 return reinterpret_cast<LRESULT>(reconv);
342 }
343
344 LRESULT InputMethodWin::OnReconvertString(RECONVERTSTRING *reconv) {
345 TextInputClient* client = GetTextInputClient();
346 if (!client)
347 return 0;
348
349 // If there is a composition string already, we don't allow reconversion.
350 if (client->HasCompositionText())
351 return 0;
352
353 ui::Range text_range;
354 if (!client->GetTextRange(&text_range) || text_range.is_empty())
355 return 0;
356
357 ui::Range selection_range;
358 if (!client->GetSelectionRange(&selection_range) ||
359 selection_range.is_empty()) {
360 return 0;
361 }
362
363 DCHECK(text_range.Contains(selection_range));
364
365 size_t len = selection_range.length();
James Su 2011/10/28 04:20:45 If you really don't want to return extra surroundi
Peng 2011/10/28 15:42:19 Done.
366 size_t need_size = sizeof(RECONVERTSTRING) + len * sizeof(WCHAR);
367
368 if (!reconv)
369 return need_size;
370
371 if (reconv->dwSize < need_size)
372 return 0;
373
374 string16 text;
375 if (!GetTextInputClient()->GetTextFromRange(selection_range, &text))
James Su 2011/10/28 04:20:45 nit: check the text length in case it's shorter th
Peng 2011/10/28 15:42:19 The API guarantee the text has right size with giv
376 return 0;
377
378 reconv->dwVersion = 0;
379 reconv->dwStrLen = len;
380 reconv->dwStrOffset = sizeof(RECONVERTSTRING);
381 reconv->dwCompStrLen = len;
382 reconv->dwCompStrOffset = 0;
383 reconv->dwTargetStrLen = len;
384 reconv->dwTargetStrOffset = 0;
385
386 memcpy(reinterpret_cast<char*>(reconv) + sizeof(RECONVERTSTRING),
387 text.c_str(), len * sizeof(WCHAR));
388
389 return reinterpret_cast<LRESULT>(reconv);
James Su 2011/10/28 04:20:45 Though msdn says that this method should return th
Peng 2011/10/28 15:42:19 I am not sure. Most IME just tests the return valu
390 }
391
257 void InputMethodWin::ConfirmCompositionText() { 392 void InputMethodWin::ConfirmCompositionText() {
258 if (!IsTextInputTypeNone()) { 393 if (!IsTextInputTypeNone()) {
259 ime_input_.CleanupComposition(hwnd()); 394 ime_input_.CleanupComposition(hwnd());
260 // Though above line should confirm the client's composition text by sending 395 // Though above line should confirm the client's composition text by sending
261 // a result text to us, in case the input method and the client are in 396 // a result text to us, in case the input method and the client are in
262 // inconsistent states, we check the client's composition state again. 397 // inconsistent states, we check the client's composition state again.
263 if (GetTextInputClient()->HasCompositionText()) 398 if (GetTextInputClient()->HasCompositionText())
264 GetTextInputClient()->ConfirmCompositionText(); 399 GetTextInputClient()->ConfirmCompositionText();
265 } 400 }
266 } 401 }
267 402
268 void InputMethodWin::UpdateIMEState() { 403 void InputMethodWin::UpdateIMEState() {
269 // Use switch here in case we are going to add more text input types. 404 // Use switch here in case we are going to add more text input types.
270 // We disable input method in password field. 405 // We disable input method in password field.
271 switch (GetTextInputType()) { 406 switch (GetTextInputType()) {
272 case ui::TEXT_INPUT_TYPE_NONE: 407 case ui::TEXT_INPUT_TYPE_NONE:
273 case ui::TEXT_INPUT_TYPE_PASSWORD: 408 case ui::TEXT_INPUT_TYPE_PASSWORD:
274 ime_input_.DisableIME(hwnd()); 409 ime_input_.DisableIME(hwnd());
275 break; 410 break;
276 default: 411 default:
277 ime_input_.EnableIME(hwnd()); 412 ime_input_.EnableIME(hwnd());
278 break; 413 break;
279 } 414 }
280 } 415 }
281 416
282 } // namespace views 417 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698