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_store.h" | 5 #include "win8/metro_driver/ime/text_store.h" |
6 | 6 |
| 7 #include <stddef.h> |
| 8 #include <stdint.h> |
| 9 |
7 #include <algorithm> | 10 #include <algorithm> |
8 | 11 |
9 #include "base/win/scoped_variant.h" | 12 #include "base/win/scoped_variant.h" |
10 #include "ui/base/win/atl_module.h" | 13 #include "ui/base/win/atl_module.h" |
11 #include "win8/metro_driver/ime/input_scope.h" | 14 #include "win8/metro_driver/ime/input_scope.h" |
12 #include "win8/metro_driver/ime/text_store_delegate.h" | 15 #include "win8/metro_driver/ime/text_store_delegate.h" |
13 | 16 |
14 namespace metro_driver { | 17 namespace metro_driver { |
15 namespace { | 18 namespace { |
16 | 19 |
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
297 return TS_E_INVALIDPOS; | 300 return TS_E_INVALIDPOS; |
298 } | 301 } |
299 | 302 |
300 // According to a behavior of notepad.exe and wordpad.exe, top left corner of | 303 // According to a behavior of notepad.exe and wordpad.exe, top left corner of |
301 // rect indicates a first character's one, and bottom right corner of rect | 304 // rect indicates a first character's one, and bottom right corner of rect |
302 // indicates a last character's one. | 305 // indicates a last character's one. |
303 // We use RECT instead of gfx::Rect since left position may be bigger than | 306 // We use RECT instead of gfx::Rect since left position may be bigger than |
304 // right position when composition has multiple lines. | 307 // right position when composition has multiple lines. |
305 RECT result; | 308 RECT result; |
306 RECT tmp_rect; | 309 RECT tmp_rect; |
307 const uint32 start_pos = acp_start - committed_size_; | 310 const uint32_t start_pos = acp_start - committed_size_; |
308 const uint32 end_pos = acp_end - committed_size_; | 311 const uint32_t end_pos = acp_end - committed_size_; |
309 | 312 |
310 if (start_pos == end_pos) { | 313 if (start_pos == end_pos) { |
311 // According to MSDN document, if |acp_start| and |acp_end| are equal it is | 314 // According to MSDN document, if |acp_start| and |acp_end| are equal it is |
312 // OK to just return E_INVALIDARG. | 315 // OK to just return E_INVALIDARG. |
313 // http://msdn.microsoft.com/en-us/library/ms538435 | 316 // http://msdn.microsoft.com/en-us/library/ms538435 |
314 // But when using Pinin IME of Windows 8, this method is called with the | 317 // But when using Pinin IME of Windows 8, this method is called with the |
315 // equal values of |acp_start| and |acp_end|. So we handle this condition. | 318 // equal values of |acp_start| and |acp_end|. So we handle this condition. |
316 if (start_pos == 0) { | 319 if (start_pos == 0) { |
317 if (delegate_->GetCompositionCharacterBounds(0, &tmp_rect)) { | 320 if (delegate_->GetCompositionCharacterBounds(0, &tmp_rect)) { |
318 tmp_rect.right = tmp_rect.right; | 321 tmp_rect.right = tmp_rect.right; |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
493 // Queue the lock request. | 496 // Queue the lock request. |
494 lock_queue_.push_back(lock_flags & TS_LF_READWRITE); | 497 lock_queue_.push_back(lock_flags & TS_LF_READWRITE); |
495 *result = TS_S_ASYNC; | 498 *result = TS_S_ASYNC; |
496 return S_OK; | 499 return S_OK; |
497 } | 500 } |
498 | 501 |
499 // Lock | 502 // Lock |
500 current_lock_type_ = (lock_flags & TS_LF_READWRITE); | 503 current_lock_type_ = (lock_flags & TS_LF_READWRITE); |
501 | 504 |
502 edit_flag_ = false; | 505 edit_flag_ = false; |
503 const uint32 last_committed_size = committed_size_; | 506 const uint32_t last_committed_size = committed_size_; |
504 | 507 |
505 // Grant the lock. | 508 // Grant the lock. |
506 *result = text_store_acp_sink_->OnLockGranted(current_lock_type_); | 509 *result = text_store_acp_sink_->OnLockGranted(current_lock_type_); |
507 | 510 |
508 // Unlock | 511 // Unlock |
509 current_lock_type_ = 0; | 512 current_lock_type_ = 0; |
510 | 513 |
511 // Handles the pending lock requests. | 514 // Handles the pending lock requests. |
512 while (!lock_queue_.empty()) { | 515 while (!lock_queue_.empty()) { |
513 current_lock_type_ = lock_queue_.front(); | 516 current_lock_type_ = lock_queue_.front(); |
514 lock_queue_.pop_front(); | 517 lock_queue_.pop_front(); |
515 text_store_acp_sink_->OnLockGranted(current_lock_type_); | 518 text_store_acp_sink_->OnLockGranted(current_lock_type_); |
516 current_lock_type_ = 0; | 519 current_lock_type_ = 0; |
517 } | 520 } |
518 | 521 |
519 if (!edit_flag_) | 522 if (!edit_flag_) |
520 return S_OK; | 523 return S_OK; |
521 | 524 |
522 // If the text store is edited in OnLockGranted(), we may need to call | 525 // If the text store is edited in OnLockGranted(), we may need to call |
523 // TextStoreDelegate::ConfirmComposition() or | 526 // TextStoreDelegate::ConfirmComposition() or |
524 // TextStoreDelegate::SetComposition(). | 527 // TextStoreDelegate::SetComposition(). |
525 const uint32 new_committed_size = committed_size_; | 528 const uint32_t new_committed_size = committed_size_; |
526 const base::string16& new_committed_string = | 529 const base::string16& new_committed_string = |
527 string_buffer_.substr(last_committed_size, | 530 string_buffer_.substr(last_committed_size, |
528 new_committed_size - last_committed_size); | 531 new_committed_size - last_committed_size); |
529 const base::string16& composition_string = | 532 const base::string16& composition_string = |
530 string_buffer_.substr(new_committed_size); | 533 string_buffer_.substr(new_committed_size); |
531 | 534 |
532 // If there is new committed string, calls | 535 // If there is new committed string, calls |
533 // TextStoreDelegate::ConfirmComposition(). | 536 // TextStoreDelegate::ConfirmComposition(). |
534 if ((!new_committed_string.empty())) | 537 if ((!new_committed_string.empty())) |
535 delegate_->OnTextCommitted(new_committed_string); | 538 delegate_->OnTextCommitted(new_committed_string); |
536 | 539 |
537 // Calls TextInputClient::SetCompositionText(). | 540 // Calls TextInputClient::SetCompositionText(). |
538 std::vector<metro_viewer::UnderlineInfo> underlines = underlines_; | 541 std::vector<metro_viewer::UnderlineInfo> underlines = underlines_; |
539 // Adjusts the offset. | 542 // Adjusts the offset. |
540 for (size_t i = 0; i < underlines_.size(); ++i) { | 543 for (size_t i = 0; i < underlines_.size(); ++i) { |
541 underlines[i].start_offset -= new_committed_size; | 544 underlines[i].start_offset -= new_committed_size; |
542 underlines[i].end_offset -= new_committed_size; | 545 underlines[i].end_offset -= new_committed_size; |
543 } | 546 } |
544 int32 selection_start = 0; | 547 int32_t selection_start = 0; |
545 int32 selection_end = 0; | 548 int32_t selection_end = 0; |
546 if (selection_start_ >= new_committed_size) | 549 if (selection_start_ >= new_committed_size) |
547 selection_start = selection_start_ - new_committed_size; | 550 selection_start = selection_start_ - new_committed_size; |
548 if (selection_end_ >= new_committed_size) | 551 if (selection_end_ >= new_committed_size) |
549 selection_end = selection_end_ - new_committed_size; | 552 selection_end = selection_end_ - new_committed_size; |
550 delegate_->OnCompositionChanged( | 553 delegate_->OnCompositionChanged( |
551 composition_string, selection_start, selection_end, underlines); | 554 composition_string, selection_start, selection_end, underlines); |
552 | 555 |
553 // If there is no composition string, clear the text store status. | 556 // If there is no composition string, clear the text store status. |
554 // And call OnSelectionChange(), OnLayoutChange(), and OnTextChange(). | 557 // And call OnSelectionChange(), OnLayoutChange(), and OnTextChange(). |
555 if ((composition_string.empty()) && (new_committed_size != 0)) { | 558 if ((composition_string.empty()) && (new_committed_size != 0)) { |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
720 if (FAILED(display_attribute_manager_->GetDisplayAttributeInfo( | 723 if (FAILED(display_attribute_manager_->GetDisplayAttributeInfo( |
721 guid, display_attribute_info.Receive(), NULL))) { | 724 guid, display_attribute_info.Receive(), NULL))) { |
722 return false; | 725 return false; |
723 } | 726 } |
724 return SUCCEEDED(display_attribute_info->GetAttributeInfo(attribute)); | 727 return SUCCEEDED(display_attribute_info->GetAttributeInfo(attribute)); |
725 } | 728 } |
726 | 729 |
727 bool TextStore::GetCompositionStatus( | 730 bool TextStore::GetCompositionStatus( |
728 ITfContext* context, | 731 ITfContext* context, |
729 const TfEditCookie read_only_edit_cookie, | 732 const TfEditCookie read_only_edit_cookie, |
730 uint32* committed_size, | 733 uint32_t* committed_size, |
731 std::vector<metro_viewer::UnderlineInfo>* undelines) { | 734 std::vector<metro_viewer::UnderlineInfo>* undelines) { |
732 DCHECK(context); | 735 DCHECK(context); |
733 DCHECK(committed_size); | 736 DCHECK(committed_size); |
734 DCHECK(undelines); | 737 DCHECK(undelines); |
735 const GUID* rgGuids[2] = {&GUID_PROP_COMPOSING, &GUID_PROP_ATTRIBUTE}; | 738 const GUID* rgGuids[2] = {&GUID_PROP_COMPOSING, &GUID_PROP_ATTRIBUTE}; |
736 base::win::ScopedComPtr<ITfReadOnlyProperty> track_property; | 739 base::win::ScopedComPtr<ITfReadOnlyProperty> track_property; |
737 if (FAILED(context->TrackProperties(rgGuids, 2, NULL, 0, | 740 if (FAILED(context->TrackProperties(rgGuids, 2, NULL, 0, |
738 track_property.Receive()))) { | 741 track_property.Receive()))) { |
739 return false; | 742 return false; |
740 } | 743 } |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
812 return true; | 815 return true; |
813 | 816 |
814 // Unlike ImmNotifyIME(NI_COMPOSITIONSTR, CPS_CANCEL, 0) in IMM32, TSF does | 817 // Unlike ImmNotifyIME(NI_COMPOSITIONSTR, CPS_CANCEL, 0) in IMM32, TSF does |
815 // not have a dedicated method to cancel composition. However, CUAS actually | 818 // not have a dedicated method to cancel composition. However, CUAS actually |
816 // has a protocol conversion from CPS_CANCEL into TSF operations. According | 819 // has a protocol conversion from CPS_CANCEL into TSF operations. According |
817 // to the observations on Windows 7, TIPs are expected to cancel composition | 820 // to the observations on Windows 7, TIPs are expected to cancel composition |
818 // when an on-going composition text is replaced with an empty string. So | 821 // when an on-going composition text is replaced with an empty string. So |
819 // we use the same operation to cancel composition here to minimize the risk | 822 // we use the same operation to cancel composition here to minimize the risk |
820 // of potential compatibility issues. | 823 // of potential compatibility issues. |
821 | 824 |
822 const uint32 previous_buffer_size = | 825 const uint32_t previous_buffer_size = |
823 static_cast<uint32>(string_buffer_.size()); | 826 static_cast<uint32_t>(string_buffer_.size()); |
824 string_buffer_.clear(); | 827 string_buffer_.clear(); |
825 committed_size_ = 0; | 828 committed_size_ = 0; |
826 selection_start_ = 0; | 829 selection_start_ = 0; |
827 selection_end_ = 0; | 830 selection_end_ = 0; |
828 if (text_store_acp_sink_mask_ & TS_AS_SEL_CHANGE) | 831 if (text_store_acp_sink_mask_ & TS_AS_SEL_CHANGE) |
829 text_store_acp_sink_->OnSelectionChange(); | 832 text_store_acp_sink_->OnSelectionChange(); |
830 if (text_store_acp_sink_mask_ & TS_AS_LAYOUT_CHANGE) | 833 if (text_store_acp_sink_mask_ & TS_AS_LAYOUT_CHANGE) |
831 text_store_acp_sink_->OnLayoutChange(TS_LC_CHANGE, 0); | 834 text_store_acp_sink_->OnLayoutChange(TS_LC_CHANGE, 0); |
832 if (text_store_acp_sink_mask_ & TS_AS_TEXT_CHANGE) { | 835 if (text_store_acp_sink_mask_ & TS_AS_TEXT_CHANGE) { |
833 TS_TEXTCHANGE textChange = {}; | 836 TS_TEXTCHANGE textChange = {}; |
(...skipping 15 matching lines...) Expand all Loading... |
849 | 852 |
850 // See the comment in TextStore::CancelComposition. | 853 // See the comment in TextStore::CancelComposition. |
851 // This logic is based on the observation about how to emulate | 854 // This logic is based on the observation about how to emulate |
852 // ImmNotifyIME(NI_COMPOSITIONSTR, CPS_COMPLETE, 0) by CUAS. | 855 // ImmNotifyIME(NI_COMPOSITIONSTR, CPS_COMPLETE, 0) by CUAS. |
853 | 856 |
854 const base::string16& composition_text = | 857 const base::string16& composition_text = |
855 string_buffer_.substr(committed_size_); | 858 string_buffer_.substr(committed_size_); |
856 if (!composition_text.empty()) | 859 if (!composition_text.empty()) |
857 delegate_->OnTextCommitted(composition_text); | 860 delegate_->OnTextCommitted(composition_text); |
858 | 861 |
859 const uint32 previous_buffer_size = | 862 const uint32_t previous_buffer_size = |
860 static_cast<uint32>(string_buffer_.size()); | 863 static_cast<uint32_t>(string_buffer_.size()); |
861 string_buffer_.clear(); | 864 string_buffer_.clear(); |
862 committed_size_ = 0; | 865 committed_size_ = 0; |
863 selection_start_ = 0; | 866 selection_start_ = 0; |
864 selection_end_ = 0; | 867 selection_end_ = 0; |
865 if (text_store_acp_sink_mask_ & TS_AS_SEL_CHANGE) | 868 if (text_store_acp_sink_mask_ & TS_AS_SEL_CHANGE) |
866 text_store_acp_sink_->OnSelectionChange(); | 869 text_store_acp_sink_->OnSelectionChange(); |
867 if (text_store_acp_sink_mask_ & TS_AS_LAYOUT_CHANGE) | 870 if (text_store_acp_sink_mask_ & TS_AS_LAYOUT_CHANGE) |
868 text_store_acp_sink_->OnLayoutChange(TS_LC_CHANGE, 0); | 871 text_store_acp_sink_->OnLayoutChange(TS_LC_CHANGE, 0); |
869 if (text_store_acp_sink_mask_ & TS_AS_TEXT_CHANGE) { | 872 if (text_store_acp_sink_mask_ & TS_AS_TEXT_CHANGE) { |
870 TS_TEXTCHANGE textChange = {}; | 873 TS_TEXTCHANGE textChange = {}; |
(...skipping 14 matching lines...) Expand all Loading... |
885 | 888 |
886 bool TextStore::HasReadLock() const { | 889 bool TextStore::HasReadLock() const { |
887 return (current_lock_type_ & TS_LF_READ) == TS_LF_READ; | 890 return (current_lock_type_ & TS_LF_READ) == TS_LF_READ; |
888 } | 891 } |
889 | 892 |
890 bool TextStore::HasReadWriteLock() const { | 893 bool TextStore::HasReadWriteLock() const { |
891 return (current_lock_type_ & TS_LF_READWRITE) == TS_LF_READWRITE; | 894 return (current_lock_type_ & TS_LF_READWRITE) == TS_LF_READWRITE; |
892 } | 895 } |
893 | 896 |
894 } // namespace metro_driver | 897 } // namespace metro_driver |
OLD | NEW |