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

Unified Diff: win8/metro_driver/ime/text_store.cc

Issue 83233002: Enable basic IME functionality under Ash on Windows (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address comment from ananta. Created 7 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 side-by-side diff with in-line comments
Download patch
Index: win8/metro_driver/ime/text_store.cc
diff --git a/ui/base/ime/win/tsf_text_store.cc b/win8/metro_driver/ime/text_store.cc
similarity index 83%
copy from ui/base/ime/win/tsf_text_store.cc
copy to win8/metro_driver/ime/text_store.cc
index 0ef34b5be89a56b649abc9e3a68e1d0ab4392da4..4a8859aef7f75651102b6ce83ef39a033ab90e0e 100644
--- a/ui/base/ime/win/tsf_text_store.cc
+++ b/win8/metro_driver/ime/text_store.cc
@@ -1,9 +1,9 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#define INITGUID // required for GUID_PROP_INPUTSCOPE
-#include "ui/base/ime/win/tsf_text_store.h"
+#include "win8/metro_driver/ime/text_store.h"
#include <InputScope.h>
#include <OleCtl.h>
@@ -11,11 +11,10 @@
#include <algorithm>
#include "base/win/scoped_variant.h"
-#include "ui/base/ime/text_input_client.h"
-#include "ui/base/ime/win/tsf_input_scope.h"
-#include "ui/gfx/rect.h"
+#include "win8/metro_driver/ime/input_scope.h"
+#include "win8/metro_driver/ime/text_store_delegate.h"
-namespace ui {
+namespace metro_driver {
namespace {
// We support only one view.
@@ -23,23 +22,57 @@ const TsViewCookie kViewCookie = 1;
} // namespace
-TSFTextStore::TSFTextStore()
+TSFTextStore::TSFTextStore(HWND window_handle,
+ ITfCategoryMgr* category_manager,
+ ITfDisplayAttributeMgr* display_attribute_manager,
+ ITfInputScope* input_scope,
+ TextStoreDelegate* delegate)
: ref_count_(0),
text_store_acp_sink_mask_(0),
- window_handle_(NULL),
- text_input_client_(NULL),
+ window_handle_(window_handle),
+ delegate_(delegate),
committed_size_(0),
+ selection_start_(0),
+ selection_end_(0),
edit_flag_(false),
- current_lock_type_(0) {
- if (FAILED(category_manager_.CreateInstance(CLSID_TF_CategoryMgr))) {
- LOG(FATAL) << "Failed to initialize CategoryMgr.";
- return;
- }
- if (FAILED(display_attribute_manager_.CreateInstance(
- CLSID_TF_DisplayAttributeMgr))) {
- LOG(FATAL) << "Failed to initialize DisplayAttributeMgr.";
- return;
- }
+ current_lock_type_(0),
+ category_manager_(category_manager),
+ display_attribute_manager_(display_attribute_manager),
+ input_scope_(input_scope) {
+}
+
+// static
+scoped_refptr<TSFTextStore> TSFTextStore::Create(
+ HWND window_handle,
+ const std::vector<InputScope>& input_scopes,
+ TextStoreDelegate* delegate) {
+ if (!delegate) {
+ LOG(ERROR) << "|delegate| must be non-NULL.";
+ return scoped_refptr<TSFTextStore>();
+ }
+ base::win::ScopedComPtr<ITfCategoryMgr> category_manager;
+ if (FAILED(category_manager.CreateInstance(CLSID_TF_CategoryMgr))) {
+ LOG(ERROR) << "Failed to initialize CategoryMgr.";
+ return scoped_refptr<TSFTextStore>();
+ }
+ base::win::ScopedComPtr<ITfDisplayAttributeMgr> display_attribute_manager;
+ if (FAILED(display_attribute_manager.CreateInstance(
+ CLSID_TF_DisplayAttributeMgr))) {
+ LOG(ERROR) << "Failed to initialize DisplayAttributeMgr.";
+ return scoped_refptr<TSFTextStore>();
+ }
+ base::win::ScopedComPtr<ITfInputScope> input_scope =
+ CreteInputScope(input_scopes);
+ if (!input_scope) {
+ LOG(ERROR) << "Failed to initialize InputScope.";
+ return scoped_refptr<TSFTextStore>();
+ }
+ return scoped_refptr<TSFTextStore>(
+ new TSFTextStore(window_handle,
+ category_manager,
+ display_attribute_manager,
+ input_scope,
+ delegate));
}
TSFTextStore::~TSFTextStore() {
@@ -166,13 +199,6 @@ STDMETHODIMP TSFTextStore::GetScreenExt(TsViewCookie view_cookie, RECT* rect) {
// {0, 0, 0, 0} means that the document rect is not currently displayed.
SetRect(rect, 0, 0, 0, 0);
- if (!IsWindow(window_handle_))
- return E_FAIL;
-
- // Currently ui::TextInputClient does not expose the document rect. So use
- // the Win32 client rectangle instead.
- // TODO(yukawa): Upgrade TextInputClient so that the client can retrieve the
- // document rectangle.
RECT client_rect = {};
if (!GetClientRect(window_handle_, &client_rect))
return E_FAIL;
@@ -203,8 +229,8 @@ STDMETHODIMP TSFTextStore::GetSelection(ULONG selection_index,
*fetched_count = 0;
if ((selection_buffer_size > 0) &&
((selection_index == 0) || (selection_index == TS_DEFAULT_SELECTION))) {
- selection_buffer[0].acpStart = selection_.start();
- selection_buffer[0].acpEnd = selection_.end();
+ selection_buffer[0].acpStart = selection_start_;
+ selection_buffer[0].acpEnd = selection_end_;
selection_buffer[0].style.ase = TS_AE_END;
selection_buffer[0].style.fInterimChar = FALSE;
*fetched_count = 1;
@@ -276,8 +302,6 @@ STDMETHODIMP TSFTextStore::GetTextExt(TsViewCookie view_cookie,
BOOL* clipped) {
if (!rect || !clipped)
return E_INVALIDARG;
- if (!text_input_client_)
- return E_UNEXPECTED;
if (view_cookie != kViewCookie)
return E_INVALIDARG;
if (!HasReadLock())
@@ -294,7 +318,7 @@ STDMETHODIMP TSFTextStore::GetTextExt(TsViewCookie view_cookie,
// We use RECT instead of gfx::Rect since left position may be bigger than
// right position when composition has multiple lines.
RECT result;
- gfx::Rect tmp_rect;
+ RECT tmp_rect;
const uint32 start_pos = acp_start - committed_size_;
const uint32 end_pos = acp_end - committed_size_;
@@ -305,34 +329,27 @@ STDMETHODIMP TSFTextStore::GetTextExt(TsViewCookie view_cookie,
// But when using Pinin IME of Windows 8, this method is called with the
// equal values of |acp_start| and |acp_end|. So we handle this condition.
if (start_pos == 0) {
- if (text_input_client_->GetCompositionCharacterBounds(0, &tmp_rect)) {
- tmp_rect.set_width(0);
- result = tmp_rect.ToRECT();
+ if (delegate_->GetCompositionCharacterBounds(0, &tmp_rect)) {
+ tmp_rect.right = tmp_rect.right;
+ result = tmp_rect;
} else if (string_buffer_.size() == committed_size_) {
- result = text_input_client_->GetCaretBounds().ToRECT();
+ result = delegate_->GetCaretBounds();
} else {
return TS_E_NOLAYOUT;
}
- } else if (text_input_client_->GetCompositionCharacterBounds(start_pos - 1,
- &tmp_rect)) {
- result.left = tmp_rect.right();
- result.right = tmp_rect.right();
- result.top = tmp_rect.y();
- result.bottom = tmp_rect.bottom();
+ } else if (delegate_->GetCompositionCharacterBounds(start_pos - 1,
+ &tmp_rect)) {
+ tmp_rect.left = tmp_rect.right;
+ result = tmp_rect;
} else {
return TS_E_NOLAYOUT;
}
} else {
- if (text_input_client_->GetCompositionCharacterBounds(start_pos,
- &tmp_rect)) {
- result.left = tmp_rect.x();
- result.top = tmp_rect.y();
- result.right = tmp_rect.right();
- result.bottom = tmp_rect.bottom();
- if (text_input_client_->GetCompositionCharacterBounds(end_pos - 1,
- &tmp_rect)) {
- result.right = tmp_rect.right();
- result.bottom = tmp_rect.bottom();
+ if (delegate_->GetCompositionCharacterBounds(start_pos, &tmp_rect)) {
+ result = tmp_rect;
+ if (delegate_->GetCompositionCharacterBounds(end_pos - 1, &tmp_rect)) {
+ result.right = tmp_rect.right;
+ result.bottom = tmp_rect.bottom;
} else {
// We may not be able to get the last character bounds, so we use the
// first character bounds instead of returning TS_E_NOLAYOUT.
@@ -342,7 +359,7 @@ STDMETHODIMP TSFTextStore::GetTextExt(TsViewCookie view_cookie,
// it's better to return previous caret rectangle instead.
// TODO(nona, kinaba): Remove this hack.
if (start_pos == 0) {
- result = text_input_client_->GetCaretBounds().ToRECT();
+ result = delegate_->GetCaretBounds();
} else {
return TS_E_NOLAYOUT;
}
@@ -390,8 +407,8 @@ STDMETHODIMP TSFTextStore::InsertTextAtSelection(DWORD flags,
LONG* acp_start,
LONG* acp_end,
TS_TEXTCHANGE* text_change) {
- const LONG start_pos = selection_.start();
- const LONG end_pos = selection_.end();
+ const LONG start_pos = selection_start_;
+ const LONG end_pos = selection_end_;
const LONG new_end_pos = start_pos + text_buffer_size;
if (flags & TS_IAS_QUERYONLY) {
@@ -423,8 +440,8 @@ STDMETHODIMP TSFTextStore::InsertTextAtSelection(DWORD flags,
text_change->acpOldEnd = end_pos;
text_change->acpNewEnd = new_end_pos;
}
- selection_.set_start(start_pos);
- selection_.set_end(new_end_pos);
+ selection_start_ = start_pos;
+ selection_end_ = new_end_pos;
return S_OK;
}
@@ -516,12 +533,12 @@ STDMETHODIMP TSFTextStore::RequestLock(DWORD lock_flags, HRESULT* result) {
current_lock_type_ = 0;
}
- if (!edit_flag_) {
+ if (!edit_flag_)
return S_OK;
- }
// If the text store is edited in OnLockGranted(), we may need to call
- // TextInputClient::InsertText() or TextInputClient::SetCompositionText().
+ // TextStoreDelegate::ConfirmComposition() or
+ // TextStoreDelegate::SetComposition().
const size_t new_committed_size = committed_size_;
const string16& new_committed_string =
string_buffer_.substr(last_committed_size,
@@ -529,41 +546,34 @@ STDMETHODIMP TSFTextStore::RequestLock(DWORD lock_flags, HRESULT* result) {
const string16& composition_string =
string_buffer_.substr(new_committed_size);
- // If there is new committed string, calls TextInputClient::InsertText().
- if ((!new_committed_string.empty()) && text_input_client_) {
- text_input_client_->InsertText(new_committed_string);
- }
+ // If there is new committed string, calls
+ // TextStoreDelegate::ConfirmComposition().
+ if ((!new_committed_string.empty()))
+ delegate_->OnTextCommitted(new_committed_string);
// Calls TextInputClient::SetCompositionText().
- CompositionText composition_text;
- composition_text.text = composition_string;
- composition_text.underlines = composition_undelines_;
+ std::vector<metro_viewer::UnderlineInfo> underlines = underlines_;
// Adjusts the offset.
- for (size_t i = 0; i < composition_text.underlines.size(); ++i) {
- composition_text.underlines[i].start_offset -= new_committed_size;
- composition_text.underlines[i].end_offset -= new_committed_size;
- }
- if (selection_.start() < new_committed_size) {
- composition_text.selection.set_start(0);
- } else {
- composition_text.selection.set_start(
- selection_.start() - new_committed_size);
- }
- if (selection_.end() < new_committed_size) {
- composition_text.selection.set_end(0);
- } else {
- composition_text.selection.set_end(selection_.end() - new_committed_size);
- }
- if (text_input_client_)
- text_input_client_->SetCompositionText(composition_text);
+ for (size_t i = 0; i < underlines_.size(); ++i) {
+ underlines[i].start_offset -= new_committed_size;
+ underlines[i].end_offset -= new_committed_size;
+ }
+ int32 selection_start = 0;
+ int32 selection_end = 0;
+ if (selection_start_ >= new_committed_size)
+ selection_start = selection_start_ - new_committed_size;
+ if (selection_end_ >= new_committed_size)
+ selection_end = selection_end_ - new_committed_size;
+ delegate_->OnCompositionChanged(
+ composition_string, selection_start, selection_end, underlines);
// If there is no composition string, clear the text store status.
// And call OnSelectionChange(), OnLayoutChange(), and OnTextChange().
if ((composition_string.empty()) && (new_committed_size != 0)) {
string_buffer_.clear();
committed_size_ = 0;
- selection_.set_start(0);
- selection_.set_end(0);
+ selection_start_ = 0;
+ selection_end_ = 0;
if (text_store_acp_sink_mask_ & TS_AS_SEL_CHANGE)
text_store_acp_sink_->OnSelectionChange();
if (text_store_acp_sink_mask_ & TS_AS_LAYOUT_CHANGE)
@@ -586,7 +596,7 @@ STDMETHODIMP TSFTextStore::RequestSupportedAttrs(
const TS_ATTRID* attribute_buffer) {
if (!attribute_buffer)
return E_INVALIDARG;
- if (!text_input_client_)
+ if (!input_scope_)
return E_FAIL;
// We support only input scope attribute.
for (size_t i = 0; i < attribute_buffer_size; ++i) {
@@ -602,9 +612,10 @@ STDMETHODIMP TSFTextStore::RetrieveRequestedAttrs(
ULONG* attribute_buffer_copied) {
if (!attribute_buffer_copied)
return E_INVALIDARG;
+ *attribute_buffer_copied = 0;
if (!attribute_buffer)
return E_INVALIDARG;
- if (!text_input_client_)
+ if (!input_scope_)
return E_UNEXPECTED;
// We support only input scope attribute.
*attribute_buffer_copied = 0;
@@ -614,9 +625,7 @@ STDMETHODIMP TSFTextStore::RetrieveRequestedAttrs(
attribute_buffer[0].dwOverlapId = 0;
attribute_buffer[0].idAttr = GUID_PROP_INPUTSCOPE;
attribute_buffer[0].varValue.vt = VT_UNKNOWN;
- attribute_buffer[0].varValue.punkVal = tsf_inputscope::CreateInputScope(
- text_input_client_->GetTextInputType(),
- text_input_client_->GetTextInputMode());
+ attribute_buffer[0].varValue.punkVal = input_scope_.get();
attribute_buffer[0].varValue.punkVal->AddRef();
*attribute_buffer_copied = 1;
return S_OK;
@@ -635,8 +644,8 @@ STDMETHODIMP TSFTextStore::SetSelection(
(end_pos <= static_cast<LONG>(string_buffer_.size())))) {
return TF_E_INVALIDPOS;
}
- selection_.set_start(start_pos);
- selection_.set_end(end_pos);
+ selection_start_ = start_pos;
+ selection_end_ = end_pos;
}
return S_OK;
}
@@ -706,19 +715,14 @@ STDMETHODIMP TSFTextStore::OnEndComposition(
}
STDMETHODIMP TSFTextStore::OnEndEdit(ITfContext* context,
- TfEditCookie read_only_edit_cookie,
- ITfEditRecord* edit_record) {
+ TfEditCookie read_only_edit_cookie,
+ ITfEditRecord* edit_record) {
if (!context || !edit_record)
return E_INVALIDARG;
-
- size_t committed_size;
- CompositionUnderlines undelines;
- if (!GetCompositionStatus(context, read_only_edit_cookie, &committed_size,
- &undelines)) {
+ if (!GetCompositionStatus(context, read_only_edit_cookie, &committed_size_,
+ &underlines_)) {
return S_OK;
}
- composition_undelines_ = undelines;
- committed_size_ = committed_size;
edit_flag_ = true;
return S_OK;
}
@@ -741,7 +745,7 @@ bool TSFTextStore::GetCompositionStatus(
ITfContext* context,
const TfEditCookie read_only_edit_cookie,
size_t* committed_size,
- CompositionUnderlines* undelines) {
+ std::vector<metro_viewer::UnderlineInfo>* undelines) {
DCHECK(context);
DCHECK(committed_size);
DCHECK(undelines);
@@ -810,33 +814,16 @@ bool TSFTextStore::GetCompositionStatus(
if (*committed_size < static_cast<size_t>(start_pos + length))
*committed_size = start_pos + length;
} else {
- CompositionUnderline underline;
+ metro_viewer::UnderlineInfo underline;
underline.start_offset = start_pos;
underline.end_offset = start_pos + length;
- underline.color = SK_ColorBLACK;
- if (has_display_attribute)
- underline.thick = !!display_attribute.fBoldLine;
+ underline.thick = !!display_attribute.fBoldLine;
undelines->push_back(underline);
}
}
return true;
}
-void TSFTextStore::SetFocusedTextInputClient(
- HWND focused_window,
- TextInputClient* text_input_client) {
- window_handle_ = focused_window;
- text_input_client_ = text_input_client;
-}
-
-void TSFTextStore::RemoveFocusedTextInputClient(
- TextInputClient* text_input_client) {
- if (text_input_client_ == text_input_client) {
- window_handle_ = NULL;
- text_input_client_ = NULL;
- }
-}
-
bool TSFTextStore::CancelComposition() {
// If there is an on-going document lock, we must not edit the text.
if (edit_flag_)
@@ -856,8 +843,8 @@ bool TSFTextStore::CancelComposition() {
const size_t previous_buffer_size = string_buffer_.size();
string_buffer_.clear();
committed_size_ = 0;
- selection_.set_start(0);
- selection_.set_end(0);
+ selection_start_ = 0;
+ selection_end_ = 0;
if (text_store_acp_sink_mask_ & TS_AS_SEL_CHANGE)
text_store_acp_sink_->OnSelectionChange();
if (text_store_acp_sink_mask_ & TS_AS_LAYOUT_CHANGE)
@@ -886,13 +873,13 @@ bool TSFTextStore::ConfirmComposition() {
const string16& composition_text = string_buffer_.substr(committed_size_);
if (!composition_text.empty())
- text_input_client_->InsertText(composition_text);
+ delegate_->OnTextCommitted(composition_text);
const size_t previous_buffer_size = string_buffer_.size();
string_buffer_.clear();
committed_size_ = 0;
- selection_.set_start(0);
- selection_.set_end(0);
+ selection_start_ = 0;
+ selection_end_ = 0;
if (text_store_acp_sink_mask_ & TS_AS_SEL_CHANGE)
text_store_acp_sink_->OnSelectionChange();
if (text_store_acp_sink_mask_ & TS_AS_LAYOUT_CHANGE)
@@ -920,4 +907,4 @@ bool TSFTextStore::HasReadWriteLock() const {
return (current_lock_type_ & TS_LF_READWRITE) == TS_LF_READWRITE;
}
-} // namespace ui
+} // namespace metro_driver

Powered by Google App Engine
This is Rietveld 408576698