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

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: Rebase 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
« no previous file with comments | « views/ime/input_method_win.h ('k') | views/ime/text_input_client.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 // Extra number of chars before and after selection (or composition) range which
14 // is returned to IME for improving conversion accuracy.
15 static const size_t kExtraNumberOfChars = 20;
16
13 namespace views { 17 namespace views {
14 18
15 InputMethodWin::InputMethodWin(internal::InputMethodDelegate* delegate) 19 InputMethodWin::InputMethodWin(internal::InputMethodDelegate* delegate)
16 : active_(false), 20 : active_(false),
17 direction_(base::i18n::UNKNOWN_DIRECTION), 21 direction_(base::i18n::UNKNOWN_DIRECTION),
18 pending_requested_direction_(base::i18n::UNKNOWN_DIRECTION) { 22 pending_requested_direction_(base::i18n::UNKNOWN_DIRECTION) {
19 set_delegate(delegate); 23 set_delegate(delegate);
20 } 24 }
21 25
22 InputMethodWin::~InputMethodWin() { 26 InputMethodWin::~InputMethodWin() {
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
108 break; 112 break;
109 case WM_IME_STARTCOMPOSITION: 113 case WM_IME_STARTCOMPOSITION:
110 result = OnImeStartComposition(message, w_param, l_param, handled); 114 result = OnImeStartComposition(message, w_param, l_param, handled);
111 break; 115 break;
112 case WM_IME_COMPOSITION: 116 case WM_IME_COMPOSITION:
113 result = OnImeComposition(message, w_param, l_param, handled); 117 result = OnImeComposition(message, w_param, l_param, handled);
114 break; 118 break;
115 case WM_IME_ENDCOMPOSITION: 119 case WM_IME_ENDCOMPOSITION:
116 result = OnImeEndComposition(message, w_param, l_param, handled); 120 result = OnImeEndComposition(message, w_param, l_param, handled);
117 break; 121 break;
122 case WM_IME_REQUEST:
123 result = OnImeRequest(message, w_param, l_param, handled);
124 break;
118 case WM_CHAR: 125 case WM_CHAR:
119 case WM_SYSCHAR: 126 case WM_SYSCHAR:
120 result = OnChar(message, w_param, l_param, handled); 127 result = OnChar(message, w_param, l_param, handled);
121 break; 128 break;
122 case WM_DEADCHAR: 129 case WM_DEADCHAR:
123 case WM_SYSDEADCHAR: 130 case WM_SYSDEADCHAR:
124 result = OnDeadChar(message, w_param, l_param, handled); 131 result = OnDeadChar(message, w_param, l_param, handled);
125 break; 132 break;
126 default: 133 default:
127 NOTREACHED() << "Unknown IME message:" << message; 134 NOTREACHED() << "Unknown IME message:" << message;
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
212 return 0; 219 return 0;
213 220
214 if (GetTextInputClient()->HasCompositionText()) 221 if (GetTextInputClient()->HasCompositionText())
215 GetTextInputClient()->ClearCompositionText(); 222 GetTextInputClient()->ClearCompositionText();
216 223
217 ime_input_.ResetComposition(hwnd()); 224 ime_input_.ResetComposition(hwnd());
218 ime_input_.DestroyImeWindow(hwnd()); 225 ime_input_.DestroyImeWindow(hwnd());
219 return 0; 226 return 0;
220 } 227 }
221 228
229 LRESULT InputMethodWin::OnImeRequest(
230 UINT message, WPARAM wparam, LPARAM lparam, BOOL* handled) {
231 *handled = FALSE;
232
233 // Should not receive WM_IME_REQUEST message, if IME is disabled.
234 const ui::TextInputType type = GetTextInputType();
235 if (type == ui::TEXT_INPUT_TYPE_NONE ||
236 type == ui::TEXT_INPUT_TYPE_PASSWORD) {
237 return 0;
238 }
239
240 switch (wparam) {
241 case IMR_RECONVERTSTRING:
242 *handled = TRUE;
243 return OnReconvertString(reinterpret_cast<RECONVERTSTRING*>(lparam));
244 case IMR_DOCUMENTFEED:
245 *handled = TRUE;
246 return OnDocumentFeed(reinterpret_cast<RECONVERTSTRING*>(lparam));
247 default:
248 return 0;
249 }
250 }
251
222 LRESULT InputMethodWin::OnChar( 252 LRESULT InputMethodWin::OnChar(
223 UINT message, WPARAM wparam, LPARAM lparam, BOOL* handled) { 253 UINT message, WPARAM wparam, LPARAM lparam, BOOL* handled) {
224 *handled = TRUE; 254 *handled = TRUE;
225 255
226 // We need to send character events to the focused text input client event if 256 // 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. 257 // its text input type is ui::TEXT_INPUT_TYPE_NONE.
228 if (!GetTextInputClient()) 258 if (!GetTextInputClient())
229 return 0; 259 return 0;
230 260
231 int flags = 0; 261 int flags = 0;
(...skipping 15 matching lines...) Expand all
247 // what dead key was pressed. 277 // what dead key was pressed.
248 ui::CompositionText composition; 278 ui::CompositionText composition;
249 composition.text.assign(1, static_cast<char16>(wparam)); 279 composition.text.assign(1, static_cast<char16>(wparam));
250 composition.selection = ui::Range(0, 1); 280 composition.selection = ui::Range(0, 1);
251 composition.underlines.push_back( 281 composition.underlines.push_back(
252 ui::CompositionUnderline(0, 1, SK_ColorBLACK, false)); 282 ui::CompositionUnderline(0, 1, SK_ColorBLACK, false));
253 GetTextInputClient()->SetCompositionText(composition); 283 GetTextInputClient()->SetCompositionText(composition);
254 return 0; 284 return 0;
255 } 285 }
256 286
287 LRESULT InputMethodWin::OnDocumentFeed(RECONVERTSTRING* reconv) {
288 TextInputClient* client = GetTextInputClient();
289 if (!client)
290 return 0;
291
292 ui::Range text_range;
293 if (!client->GetTextRange(&text_range) || text_range.is_empty())
294 return 0;
295
296 bool result = false;
297 ui::Range target_range;
298 if (client->HasCompositionText())
299 result = client->GetCompositionTextRange(&target_range);
300
301 if (!result || target_range.is_empty()) {
302 if (!client->GetSelectionRange(&target_range) ||
303 !target_range.IsValid()) {
304 return 0;
305 }
306 }
307
308 if (!text_range.Contains(target_range))
309 return 0;
310
311 if (target_range.GetMin() - text_range.start() > kExtraNumberOfChars)
312 text_range.set_start(target_range.GetMin() - kExtraNumberOfChars);
313
314 if (text_range.end() - target_range.GetMax() > kExtraNumberOfChars)
315 text_range.set_end(target_range.GetMax() + kExtraNumberOfChars);
316
317 size_t len = text_range.length();
318 size_t need_size = sizeof(RECONVERTSTRING) + len * sizeof(WCHAR);
319
320 if (!reconv)
321 return need_size;
322
323 if (reconv->dwSize < need_size)
324 return 0;
325
326 string16 text;
327 if (!GetTextInputClient()->GetTextFromRange(text_range, &text))
328 return 0;
329 DCHECK_EQ(text_range.length(), text.length());
330
331 reconv->dwVersion = 0;
332 reconv->dwStrLen = len;
333 reconv->dwStrOffset = sizeof(RECONVERTSTRING);
334 reconv->dwCompStrLen =
335 client->HasCompositionText() ? target_range.length() : 0;
336 reconv->dwCompStrOffset =
337 (target_range.GetMin() - text_range.start()) * sizeof(WCHAR);
338 reconv->dwTargetStrLen = target_range.length();
339 reconv->dwTargetStrOffset = reconv->dwCompStrOffset;
340
341 memcpy((char*)reconv + sizeof(RECONVERTSTRING),
342 text.c_str(), len * sizeof(WCHAR));
343
344 // According to Microsft API document, IMR_RECONVERTSTRING and
345 // IMR_DOCUMENTFEED should return reconv, but some applications return
346 // need_size.
347 return reinterpret_cast<LRESULT>(reconv);
348 }
349
350 LRESULT InputMethodWin::OnReconvertString(RECONVERTSTRING* reconv) {
351 TextInputClient* client = GetTextInputClient();
352 if (!client)
353 return 0;
354
355 // If there is a composition string already, we don't allow reconversion.
356 if (client->HasCompositionText())
357 return 0;
358
359 ui::Range text_range;
360 if (!client->GetTextRange(&text_range) || text_range.is_empty())
361 return 0;
362
363 ui::Range selection_range;
364 if (!client->GetSelectionRange(&selection_range) ||
365 selection_range.is_empty()) {
366 return 0;
367 }
368
369 DCHECK(text_range.Contains(selection_range));
370
371 size_t len = selection_range.length();
372 size_t need_size = sizeof(RECONVERTSTRING) + len * sizeof(WCHAR);
373
374 if (!reconv)
375 return need_size;
376
377 if (reconv->dwSize < need_size)
378 return 0;
379
380 // TODO(penghuang): Return some extra context to help improve IME's
381 // reconversion accuracy.
382 string16 text;
383 if (!GetTextInputClient()->GetTextFromRange(selection_range, &text))
384 return 0;
385 DCHECK_EQ(selection_range.length(), text.length());
386
387 reconv->dwVersion = 0;
388 reconv->dwStrLen = len;
389 reconv->dwStrOffset = sizeof(RECONVERTSTRING);
390 reconv->dwCompStrLen = len;
391 reconv->dwCompStrOffset = 0;
392 reconv->dwTargetStrLen = len;
393 reconv->dwTargetStrOffset = 0;
394
395 memcpy(reinterpret_cast<char*>(reconv) + sizeof(RECONVERTSTRING),
396 text.c_str(), len * sizeof(WCHAR));
397
398 // According to Microsft API document, IMR_RECONVERTSTRING and
399 // IMR_DOCUMENTFEED should return reconv, but some applications return
400 // need_size.
401 return reinterpret_cast<LRESULT>(reconv);
402 }
403
257 void InputMethodWin::ConfirmCompositionText() { 404 void InputMethodWin::ConfirmCompositionText() {
258 if (!IsTextInputTypeNone()) { 405 if (!IsTextInputTypeNone()) {
259 ime_input_.CleanupComposition(hwnd()); 406 ime_input_.CleanupComposition(hwnd());
260 // Though above line should confirm the client's composition text by sending 407 // 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 408 // 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. 409 // inconsistent states, we check the client's composition state again.
263 if (GetTextInputClient()->HasCompositionText()) 410 if (GetTextInputClient()->HasCompositionText())
264 GetTextInputClient()->ConfirmCompositionText(); 411 GetTextInputClient()->ConfirmCompositionText();
265 } 412 }
266 } 413 }
267 414
268 void InputMethodWin::UpdateIMEState() { 415 void InputMethodWin::UpdateIMEState() {
269 // Use switch here in case we are going to add more text input types. 416 // Use switch here in case we are going to add more text input types.
270 // We disable input method in password field. 417 // We disable input method in password field.
271 switch (GetTextInputType()) { 418 switch (GetTextInputType()) {
272 case ui::TEXT_INPUT_TYPE_NONE: 419 case ui::TEXT_INPUT_TYPE_NONE:
273 case ui::TEXT_INPUT_TYPE_PASSWORD: 420 case ui::TEXT_INPUT_TYPE_PASSWORD:
274 ime_input_.DisableIME(hwnd()); 421 ime_input_.DisableIME(hwnd());
275 break; 422 break;
276 default: 423 default:
277 ime_input_.EnableIME(hwnd()); 424 ime_input_.EnableIME(hwnd());
278 break; 425 break;
279 } 426 }
280 } 427 }
281 428
282 } // namespace views 429 } // namespace views
OLDNEW
« no previous file with comments | « views/ime/input_method_win.h ('k') | views/ime/text_input_client.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698