| 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 |