| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "win8/metro_driver/ime/text_service.h" | 5 #include "win8/metro_driver/ime/text_service.h" |
| 6 | 6 |
| 7 #include <msctf.h> | 7 #include <msctf.h> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/win/scoped_variant.h" | 10 #include "base/win/scoped_variant.h" |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 85 // about what will be involved in this multi-phase construction. See also | 85 // about what will be involved in this multi-phase construction. See also |
| 86 // text_store.cc and input_scope.cc for more underlying details. | 86 // text_store.cc and input_scope.cc for more underlying details. |
| 87 | 87 |
| 88 namespace metro_driver { | 88 namespace metro_driver { |
| 89 namespace { | 89 namespace { |
| 90 | 90 |
| 91 // Japanese IME expects the default value of this compartment is | 91 // Japanese IME expects the default value of this compartment is |
| 92 // TF_SENTENCEMODE_PHRASEPREDICT to emulate IMM32 behavior. This value is | 92 // TF_SENTENCEMODE_PHRASEPREDICT to emulate IMM32 behavior. This value is |
| 93 // managed per thread, thus setting this value at once is sufficient. This | 93 // managed per thread, thus setting this value at once is sufficient. This |
| 94 // value never affects non-Japanese IMEs. | 94 // value never affects non-Japanese IMEs. |
| 95 bool InitializeSentenceMode(ITfThreadMgr2* thread_manager, | 95 bool InitializeSentenceMode(ITfThreadMgr* thread_manager, |
| 96 TfClientId client_id) { | 96 TfClientId client_id) { |
| 97 base::win::ScopedComPtr<ITfCompartmentMgr> thread_compartment_manager; | 97 base::win::ScopedComPtr<ITfCompartmentMgr> thread_compartment_manager; |
| 98 HRESULT hr = thread_compartment_manager.QueryFrom(thread_manager); | 98 HRESULT hr = thread_compartment_manager.QueryFrom(thread_manager); |
| 99 if (FAILED(hr)) { | 99 if (FAILED(hr)) { |
| 100 LOG(ERROR) << "QueryFrom failed. hr = " << hr; | 100 LOG(ERROR) << "QueryFrom failed. hr = " << hr; |
| 101 return false; | 101 return false; |
| 102 } | 102 } |
| 103 base::win::ScopedComPtr<ITfCompartment> sentence_compartment; | 103 base::win::ScopedComPtr<ITfCompartment> sentence_compartment; |
| 104 hr = thread_compartment_manager->GetCompartment( | 104 hr = thread_compartment_manager->GetCompartment( |
| 105 GUID_COMPARTMENT_KEYBOARD_INPUTMODE_SENTENCE, | 105 GUID_COMPARTMENT_KEYBOARD_INPUTMODE_SENTENCE, |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 217 // TSF runtime and TextStore is unregistered when this object is destroyed. | 217 // TSF runtime and TextStore is unregistered when this object is destroyed. |
| 218 class DocumentBinding { | 218 class DocumentBinding { |
| 219 public: | 219 public: |
| 220 ~DocumentBinding() { | 220 ~DocumentBinding() { |
| 221 if (!document_manager_) | 221 if (!document_manager_) |
| 222 return; | 222 return; |
| 223 document_manager_->Pop(TF_POPF_ALL); | 223 document_manager_->Pop(TF_POPF_ALL); |
| 224 } | 224 } |
| 225 | 225 |
| 226 static scoped_ptr<DocumentBinding> Create( | 226 static scoped_ptr<DocumentBinding> Create( |
| 227 ITfThreadMgr2* thread_manager, | 227 ITfThreadMgr* thread_manager, |
| 228 TfClientId client_id, | 228 TfClientId client_id, |
| 229 const std::vector<InputScope>& input_scopes, | 229 const std::vector<InputScope>& input_scopes, |
| 230 HWND window_handle, | 230 HWND window_handle, |
| 231 TextStoreDelegate* delegate) { | 231 TextStoreDelegate* delegate) { |
| 232 base::win::ScopedComPtr<ITfDocumentMgr> document_manager; | 232 base::win::ScopedComPtr<ITfDocumentMgr> document_manager; |
| 233 HRESULT hr = thread_manager->CreateDocumentMgr(document_manager.Receive()); | 233 HRESULT hr = thread_manager->CreateDocumentMgr(document_manager.Receive()); |
| 234 if (FAILED(hr)) { | 234 if (FAILED(hr)) { |
| 235 LOG(ERROR) << "ITfThreadMgr2::CreateDocumentMgr failed. hr = " << hr; | 235 LOG(ERROR) << "ITfThreadMgr::CreateDocumentMgr failed. hr = " << hr; |
| 236 return scoped_ptr<DocumentBinding>(); | 236 return scoped_ptr<DocumentBinding>(); |
| 237 } | 237 } |
| 238 | 238 |
| 239 // Note: In our IPC protocol, an empty |input_scopes| is used to indicate | 239 // Note: In our IPC protocol, an empty |input_scopes| is used to indicate |
| 240 // that an IME must be disabled in this context. In such case, we need not | 240 // that an IME must be disabled in this context. In such case, we need not |
| 241 // instantiate TextStore. | 241 // instantiate TextStore. |
| 242 const bool use_null_text_store = input_scopes.empty(); | 242 const bool use_null_text_store = input_scopes.empty(); |
| 243 | 243 |
| 244 scoped_refptr<TextStore> text_store; | 244 scoped_refptr<TextStore> text_store; |
| 245 if (!use_null_text_store) { | 245 if (!use_null_text_store) { |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 309 scoped_refptr<TextStore> text_store_; | 309 scoped_refptr<TextStore> text_store_; |
| 310 base::win::ScopedComPtr<ITfDocumentMgr> document_manager_; | 310 base::win::ScopedComPtr<ITfDocumentMgr> document_manager_; |
| 311 scoped_ptr<EventSink> text_edit_sink_; | 311 scoped_ptr<EventSink> text_edit_sink_; |
| 312 | 312 |
| 313 DISALLOW_COPY_AND_ASSIGN(DocumentBinding); | 313 DISALLOW_COPY_AND_ASSIGN(DocumentBinding); |
| 314 }; | 314 }; |
| 315 | 315 |
| 316 class TextServiceImpl : public TextService, | 316 class TextServiceImpl : public TextService, |
| 317 public TextStoreDelegate { | 317 public TextStoreDelegate { |
| 318 public: | 318 public: |
| 319 TextServiceImpl(ITfThreadMgr2* thread_manager, | 319 TextServiceImpl(ITfThreadMgr* thread_manager, |
| 320 TfClientId client_id, | 320 TfClientId client_id, |
| 321 HWND window_handle, | 321 HWND window_handle, |
| 322 TextServiceDelegate* delegate) | 322 TextServiceDelegate* delegate) |
| 323 : client_id_(client_id), | 323 : client_id_(client_id), |
| 324 window_handle_(window_handle), | 324 window_handle_(window_handle), |
| 325 delegate_(delegate), | 325 delegate_(delegate), |
| 326 thread_manager_(thread_manager) { | 326 thread_manager_(thread_manager) { |
| 327 DCHECK_NE(TF_CLIENTID_NULL, client_id); | 327 DCHECK_NE(TF_CLIENTID_NULL, client_id); |
| 328 DCHECK(window_handle != NULL); | 328 DCHECK(window_handle != NULL); |
| 329 DCHECK(thread_manager_); | 329 DCHECK(thread_manager_); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 361 VLOG(0) << "|current_document_| is NULL due to the previous error."; | 361 VLOG(0) << "|current_document_| is NULL due to the previous error."; |
| 362 return; | 362 return; |
| 363 } | 363 } |
| 364 ITfDocumentMgr* document_manager = current_document_->document_manager(); | 364 ITfDocumentMgr* document_manager = current_document_->document_manager(); |
| 365 if (!document_manager) { | 365 if (!document_manager) { |
| 366 VLOG(0) << "|document_manager| is NULL due to the previous error."; | 366 VLOG(0) << "|document_manager| is NULL due to the previous error."; |
| 367 return; | 367 return; |
| 368 } | 368 } |
| 369 HRESULT hr = thread_manager_->SetFocus(document_manager); | 369 HRESULT hr = thread_manager_->SetFocus(document_manager); |
| 370 if (FAILED(hr)) { | 370 if (FAILED(hr)) { |
| 371 LOG(ERROR) << "ITfThreadMgr2::SetFocus failed. hr = " << hr; | 371 LOG(ERROR) << "ITfThreadMgr::SetFocus failed. hr = " << hr; |
| 372 return; | 372 return; |
| 373 } | 373 } |
| 374 } | 374 } |
| 375 | 375 |
| 376 virtual void OnCompositionChanged( | 376 virtual void OnCompositionChanged( |
| 377 const base::string16& text, | 377 const base::string16& text, |
| 378 int32 selection_start, | 378 int32 selection_start, |
| 379 int32 selection_end, | 379 int32 selection_end, |
| 380 const std::vector<metro_viewer::UnderlineInfo>& underlines) override { | 380 const std::vector<metro_viewer::UnderlineInfo>& underlines) override { |
| 381 if (!delegate_) | 381 if (!delegate_) |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 439 this); | 439 this); |
| 440 LOG_IF(ERROR, !new_document) << "Failed to create a new document."; | 440 LOG_IF(ERROR, !new_document) << "Failed to create a new document."; |
| 441 current_document_.swap(new_document); | 441 current_document_.swap(new_document); |
| 442 OnWindowActivated(); | 442 OnWindowActivated(); |
| 443 } | 443 } |
| 444 | 444 |
| 445 TfClientId client_id_; | 445 TfClientId client_id_; |
| 446 HWND window_handle_; | 446 HWND window_handle_; |
| 447 TextServiceDelegate* delegate_; | 447 TextServiceDelegate* delegate_; |
| 448 scoped_ptr<DocumentBinding> current_document_; | 448 scoped_ptr<DocumentBinding> current_document_; |
| 449 base::win::ScopedComPtr<ITfThreadMgr2> thread_manager_; | 449 base::win::ScopedComPtr<ITfThreadMgr> thread_manager_; |
| 450 | 450 |
| 451 // A vector of InputScope enumeration, which represents the document type of | 451 // A vector of InputScope enumeration, which represents the document type of |
| 452 // the focused text field. Note that in our IPC message protocol, an empty | 452 // the focused text field. Note that in our IPC message protocol, an empty |
| 453 // |input_scopes_| has special meaning that IMEs must be disabled on this | 453 // |input_scopes_| has special meaning that IMEs must be disabled on this |
| 454 // document. | 454 // document. |
| 455 std::vector<int32> input_scopes_; | 455 std::vector<int32> input_scopes_; |
| 456 // Character bounds of the composition. When there is no composition but this | 456 // Character bounds of the composition. When there is no composition but this |
| 457 // vector is not empty, the first element contains the caret bounds. | 457 // vector is not empty, the first element contains the caret bounds. |
| 458 std::vector<metro_viewer::CharacterBounds> composition_character_bounds_; | 458 std::vector<metro_viewer::CharacterBounds> composition_character_bounds_; |
| 459 | 459 |
| 460 DISALLOW_COPY_AND_ASSIGN(TextServiceImpl); | 460 DISALLOW_COPY_AND_ASSIGN(TextServiceImpl); |
| 461 }; | 461 }; |
| 462 | 462 |
| 463 } // namespace | 463 } // namespace |
| 464 | 464 |
| 465 scoped_ptr<TextService> | 465 scoped_ptr<TextService> |
| 466 CreateTextService(TextServiceDelegate* delegate, HWND window_handle) { | 466 CreateTextService(TextServiceDelegate* delegate, HWND window_handle) { |
| 467 if (!delegate) | 467 if (!delegate) |
| 468 return scoped_ptr<TextService>(); | 468 return scoped_ptr<TextService>(); |
| 469 base::win::ScopedComPtr<ITfThreadMgr2> thread_manager; | 469 base::win::ScopedComPtr<ITfThreadMgr> thread_manager; |
| 470 HRESULT hr = thread_manager.CreateInstance(CLSID_TF_ThreadMgr); | 470 HRESULT hr = thread_manager.CreateInstance(CLSID_TF_ThreadMgr); |
| 471 if (FAILED(hr)) { | 471 if (FAILED(hr)) { |
| 472 LOG(ERROR) << "Failed to create instance of CLSID_TF_ThreadMgr. hr = " | 472 LOG(ERROR) << "Failed to create instance of CLSID_TF_ThreadMgr. hr = " |
| 473 << hr; | 473 << hr; |
| 474 return scoped_ptr<TextService>(); | 474 return scoped_ptr<TextService>(); |
| 475 } | 475 } |
| 476 TfClientId client_id = TF_CLIENTID_NULL; | 476 TfClientId client_id = TF_CLIENTID_NULL; |
| 477 hr = thread_manager->ActivateEx(&client_id, 0); | 477 hr = thread_manager->Activate(&client_id); |
| 478 if (FAILED(hr)) { | 478 if (FAILED(hr)) { |
| 479 LOG(ERROR) << "ITfThreadMgr2::ActivateEx failed. hr = " << hr; | 479 LOG(ERROR) << "ITfThreadMgr::Activate failed. hr = " << hr; |
| 480 return scoped_ptr<TextService>(); | 480 return scoped_ptr<TextService>(); |
| 481 } | 481 } |
| 482 if (!InitializeSentenceMode(thread_manager, client_id)) { | 482 if (!InitializeSentenceMode(thread_manager, client_id)) { |
| 483 LOG(ERROR) << "InitializeSentenceMode failed."; | 483 LOG(ERROR) << "InitializeSentenceMode failed."; |
| 484 thread_manager->Deactivate(); | 484 thread_manager->Deactivate(); |
| 485 return scoped_ptr<TextService>(); | 485 return scoped_ptr<TextService>(); |
| 486 } | 486 } |
| 487 return scoped_ptr<TextService>(new TextServiceImpl(thread_manager, | 487 return scoped_ptr<TextService>(new TextServiceImpl(thread_manager, |
| 488 client_id, | 488 client_id, |
| 489 window_handle, | 489 window_handle, |
| 490 delegate)); | 490 delegate)); |
| 491 } | 491 } |
| 492 | 492 |
| 493 } // namespace metro_driver | 493 } // namespace metro_driver |
| OLD | NEW |