Chromium Code Reviews| OLD | NEW |
|---|---|
| 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" |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 108 break; | 108 break; |
| 109 case WM_IME_STARTCOMPOSITION: | 109 case WM_IME_STARTCOMPOSITION: |
| 110 result = OnImeStartComposition(message, w_param, l_param, handled); | 110 result = OnImeStartComposition(message, w_param, l_param, handled); |
| 111 break; | 111 break; |
| 112 case WM_IME_COMPOSITION: | 112 case WM_IME_COMPOSITION: |
| 113 result = OnImeComposition(message, w_param, l_param, handled); | 113 result = OnImeComposition(message, w_param, l_param, handled); |
| 114 break; | 114 break; |
| 115 case WM_IME_ENDCOMPOSITION: | 115 case WM_IME_ENDCOMPOSITION: |
| 116 result = OnImeEndComposition(message, w_param, l_param, handled); | 116 result = OnImeEndComposition(message, w_param, l_param, handled); |
| 117 break; | 117 break; |
| 118 case WM_IME_REQUEST: | |
| 119 result = OnImeRequest(message, w_param, l_param, handled); | |
| 120 break; | |
| 118 case WM_CHAR: | 121 case WM_CHAR: |
| 119 case WM_SYSCHAR: | 122 case WM_SYSCHAR: |
| 120 result = OnChar(message, w_param, l_param, handled); | 123 result = OnChar(message, w_param, l_param, handled); |
| 121 break; | 124 break; |
| 122 case WM_DEADCHAR: | 125 case WM_DEADCHAR: |
| 123 case WM_SYSDEADCHAR: | 126 case WM_SYSDEADCHAR: |
| 124 result = OnDeadChar(message, w_param, l_param, handled); | 127 result = OnDeadChar(message, w_param, l_param, handled); |
| 125 break; | 128 break; |
| 126 default: | 129 default: |
| 127 NOTREACHED() << "Unknown IME message:" << message; | 130 NOTREACHED() << "Unknown IME message:" << message; |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 212 return 0; | 215 return 0; |
| 213 | 216 |
| 214 if (GetTextInputClient()->HasCompositionText()) | 217 if (GetTextInputClient()->HasCompositionText()) |
| 215 GetTextInputClient()->ClearCompositionText(); | 218 GetTextInputClient()->ClearCompositionText(); |
| 216 | 219 |
| 217 ime_input_.ResetComposition(hwnd()); | 220 ime_input_.ResetComposition(hwnd()); |
| 218 ime_input_.DestroyImeWindow(hwnd()); | 221 ime_input_.DestroyImeWindow(hwnd()); |
| 219 return 0; | 222 return 0; |
| 220 } | 223 } |
| 221 | 224 |
| 225 LRESULT InputMethodWin::OnImeRequest( | |
| 226 UINT message, WPARAM wparam, LPARAM lparam, BOOL* handled) { | |
| 227 *handled = FALSE; | |
| 228 | |
| 229 // Should not receive WM_IME_REQUEST message, if IME is disabled. | |
| 230 ui::TextInputType type = GetTextInputType(); | |
|
James Su
2011/10/26 18:41:57
nit: const ui::TextInputType
| |
| 231 if (type == ui::TEXT_INPUT_TYPE_NONE || | |
| 232 type == ui::TEXT_INPUT_TYPE_PASSWORD) { | |
| 233 return 0; | |
| 234 } | |
| 235 | |
| 236 switch (wparam) { | |
| 237 case IMR_RECONVERTSTRING: | |
| 238 *handled = TRUE; | |
| 239 return OnReconvertString(reinterpret_cast<RECONVERTSTRING*>(lparam)); | |
| 240 case IMR_DOCUMENTFEED: | |
| 241 *handled = TRUE; | |
| 242 return OnDocumentFeed(reinterpret_cast<RECONVERTSTRING*>(lparam)); | |
| 243 default: | |
| 244 return 0; | |
| 245 } | |
| 246 } | |
| 247 | |
| 222 LRESULT InputMethodWin::OnChar( | 248 LRESULT InputMethodWin::OnChar( |
| 223 UINT message, WPARAM wparam, LPARAM lparam, BOOL* handled) { | 249 UINT message, WPARAM wparam, LPARAM lparam, BOOL* handled) { |
| 224 *handled = TRUE; | 250 *handled = TRUE; |
| 225 | 251 |
| 226 // We need to send character events to the focused text input client event if | 252 // 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. | 253 // its text input type is ui::TEXT_INPUT_TYPE_NONE. |
| 228 if (!GetTextInputClient()) | 254 if (!GetTextInputClient()) |
| 229 return 0; | 255 return 0; |
| 230 | 256 |
| 231 int flags = 0; | 257 int flags = 0; |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 247 // what dead key was pressed. | 273 // what dead key was pressed. |
| 248 ui::CompositionText composition; | 274 ui::CompositionText composition; |
| 249 composition.text.assign(1, static_cast<char16>(wparam)); | 275 composition.text.assign(1, static_cast<char16>(wparam)); |
| 250 composition.selection = ui::Range(0, 1); | 276 composition.selection = ui::Range(0, 1); |
| 251 composition.underlines.push_back( | 277 composition.underlines.push_back( |
| 252 ui::CompositionUnderline(0, 1, SK_ColorBLACK, false)); | 278 ui::CompositionUnderline(0, 1, SK_ColorBLACK, false)); |
| 253 GetTextInputClient()->SetCompositionText(composition); | 279 GetTextInputClient()->SetCompositionText(composition); |
| 254 return 0; | 280 return 0; |
| 255 } | 281 } |
| 256 | 282 |
| 283 LRESULT InputMethodWin::OnDocumentFeed(RECONVERTSTRING *reconv) { | |
| 284 TextInputClient* client = GetTextInputClient(); | |
| 285 if (!client) | |
| 286 return 0; | |
| 287 | |
| 288 ui::Range text_range; | |
| 289 if (!client->GetTextRange(&text_range) || text_range.is_empty()) | |
| 290 return 0; | |
| 291 | |
| 292 ui::Range target_range; | |
| 293 do { | |
| 294 if (client->HasCompositionText() && | |
| 295 client->GetCompositionTextRange(&target_range) && | |
| 296 !target_range.is_empty()) { | |
| 297 break; | |
| 298 } | |
| 299 if (client->GetSelectionRange(&target_range)) | |
| 300 break; | |
| 301 return 0; | |
| 302 } while (0); | |
| 303 | |
| 304 if (!text_range.Contains(target_range)) | |
| 305 return 0; | |
| 306 | |
| 307 size_t len = text_range.length(); | |
| 308 size_t need_size = sizeof(RECONVERTSTRING) + len * sizeof(WCHAR); | |
| 309 | |
| 310 if (!reconv) | |
| 311 return need_size; | |
| 312 | |
| 313 if (reconv->dwSize < need_size) | |
| 314 return 0; | |
| 315 | |
| 316 string16 text; | |
| 317 ui::Range actual_range; | |
| 318 if (!GetTextInputClient()->GetTextFromRange( | |
| 319 text_range, &text, &actual_range)) { | |
| 320 return 0; | |
| 321 } | |
| 322 | |
| 323 DCHECK(text_range == actual_range); | |
| 324 | |
| 325 reconv->dwVersion = 0; | |
| 326 reconv->dwStrLen = len; | |
| 327 reconv->dwStrOffset = sizeof(RECONVERTSTRING); | |
| 328 reconv->dwCompStrLen = | |
| 329 client->HasCompositionText() ? reconv->dwTargetStrOffset : 0; | |
| 330 reconv->dwCompStrOffset = | |
| 331 (target_range.GetMin() - text_range.start()) * sizeof(WCHAR); | |
| 332 reconv->dwTargetStrLen = target_range.length(); | |
| 333 reconv->dwTargetStrOffset = reconv->dwCompStrOffset; | |
| 334 | |
| 335 memcpy((char*)reconv + sizeof(RECONVERTSTRING), | |
| 336 text.c_str(), len * sizeof(WCHAR)); | |
| 337 | |
| 338 return need_size; | |
| 339 } | |
| 340 | |
| 341 LRESULT InputMethodWin::OnReconvertString(RECONVERTSTRING *reconv) { | |
| 342 TextInputClient* client = GetTextInputClient(); | |
| 343 if (!client) | |
| 344 return 0; | |
| 345 | |
| 346 // If there is a composition string already, we don't allow reconversion. | |
| 347 if (client->HasCompositionText()) | |
| 348 return 0; | |
| 349 | |
| 350 ui::Range text_range; | |
| 351 if (!client->GetTextRange(&text_range) || text_range.is_empty()) | |
| 352 return 0; | |
| 353 | |
| 354 ui::Range selection_range; | |
| 355 if (!client->GetSelectionRange(&selection_range) || | |
| 356 selection_range.is_empty()) { | |
| 357 return 0; | |
| 358 } | |
| 359 | |
| 360 if (!text_range.Contains(selection_range)) | |
| 361 return 0; | |
| 362 | |
| 363 size_t len = text_range.length(); | |
|
James Su
2011/10/26 18:41:57
It's better not to return all text content, becaus
| |
| 364 size_t need_size = sizeof(RECONVERTSTRING) + len * sizeof(WCHAR); | |
| 365 | |
| 366 if (!reconv) | |
| 367 return need_size; | |
| 368 | |
| 369 if (reconv->dwSize < need_size) | |
| 370 return 0; | |
| 371 | |
| 372 string16 text; | |
| 373 ui::Range actual_range; | |
| 374 if (!GetTextInputClient()->GetTextFromRange( | |
| 375 text_range, &text, &actual_range)) | |
| 376 return 0; | |
| 377 | |
| 378 reconv->dwVersion = 0; | |
| 379 reconv->dwStrLen = len; | |
| 380 reconv->dwStrOffset = sizeof(RECONVERTSTRING); | |
| 381 reconv->dwCompStrLen = selection_range.length(); | |
| 382 reconv->dwCompStrOffset = | |
| 383 (selection_range.GetMin() - text_range.start()) * sizeof(WCHAR); | |
| 384 reconv->dwTargetStrLen = reconv->dwCompStrLen; | |
| 385 reconv->dwTargetStrOffset = reconv->dwCompStrOffset; | |
| 386 memcpy(reinterpret_cast<char*>(reconv) + sizeof(RECONVERTSTRING), | |
| 387 text.c_str(), len * sizeof(WCHAR)); | |
| 388 | |
| 389 return need_size; | |
| 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 |
| OLD | NEW |