| 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 70%
|
| copy from ui/base/ime/win/tsf_text_store.cc
|
| copy to win8/metro_driver/ime/text_store.cc
|
| index 0ef34b5be89a56b649abc9e3a68e1d0ab4392da4..c2f60bbf9210103beb0e0b2f30cb9055b8361a13 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,12 +22,16 @@ const TsViewCookie kViewCookie = 1;
|
|
|
| } // namespace
|
|
|
| -TSFTextStore::TSFTextStore()
|
| +TextStore::TextStore(HWND window_handle,
|
| + const std::vector<InputScope>& input_scopes,
|
| + 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))) {
|
| @@ -40,16 +43,17 @@ TSFTextStore::TSFTextStore()
|
| LOG(FATAL) << "Failed to initialize DisplayAttributeMgr.";
|
| return;
|
| }
|
| + input_scope_ = CreteInputScope(input_scopes);
|
| }
|
|
|
| -TSFTextStore::~TSFTextStore() {
|
| +TextStore::~TextStore() {
|
| }
|
|
|
| -ULONG STDMETHODCALLTYPE TSFTextStore::AddRef() {
|
| +ULONG STDMETHODCALLTYPE TextStore::AddRef() {
|
| return InterlockedIncrement(&ref_count_);
|
| }
|
|
|
| -ULONG STDMETHODCALLTYPE TSFTextStore::Release() {
|
| +ULONG STDMETHODCALLTYPE TextStore::Release() {
|
| const LONG count = InterlockedDecrement(&ref_count_);
|
| if (!count) {
|
| delete this;
|
| @@ -58,7 +62,7 @@ ULONG STDMETHODCALLTYPE TSFTextStore::Release() {
|
| return static_cast<ULONG>(count);
|
| }
|
|
|
| -STDMETHODIMP TSFTextStore::QueryInterface(REFIID iid, void** result) {
|
| +STDMETHODIMP TextStore::QueryInterface(REFIID iid, void** result) {
|
| if (iid == IID_IUnknown || iid == IID_ITextStoreACP) {
|
| *result = static_cast<ITextStoreACP*>(this);
|
| } else if (iid == IID_ITfContextOwnerCompositionSink) {
|
| @@ -73,9 +77,9 @@ STDMETHODIMP TSFTextStore::QueryInterface(REFIID iid, void** result) {
|
| return S_OK;
|
| }
|
|
|
| -STDMETHODIMP TSFTextStore::AdviseSink(REFIID iid,
|
| - IUnknown* unknown,
|
| - DWORD mask) {
|
| +STDMETHODIMP TextStore::AdviseSink(REFIID iid,
|
| + IUnknown* unknown,
|
| + DWORD mask) {
|
| if (!IsEqualGUID(iid, IID_ITextStoreACPSink))
|
| return E_INVALIDARG;
|
| if (text_store_acp_sink_) {
|
| @@ -93,7 +97,7 @@ STDMETHODIMP TSFTextStore::AdviseSink(REFIID iid,
|
| return S_OK;
|
| }
|
|
|
| -STDMETHODIMP TSFTextStore::FindNextAttrTransition(
|
| +STDMETHODIMP TextStore::FindNextAttrTransition(
|
| LONG acp_start,
|
| LONG acp_halt,
|
| ULONG num_filter_attributes,
|
| @@ -112,17 +116,17 @@ STDMETHODIMP TSFTextStore::FindNextAttrTransition(
|
| return S_OK;
|
| }
|
|
|
| -STDMETHODIMP TSFTextStore::GetACPFromPoint(TsViewCookie view_cookie,
|
| - const POINT* point,
|
| - DWORD flags,
|
| - LONG* acp) {
|
| +STDMETHODIMP TextStore::GetACPFromPoint(TsViewCookie view_cookie,
|
| + const POINT* point,
|
| + DWORD flags,
|
| + LONG* acp) {
|
| NOTIMPLEMENTED();
|
| if (view_cookie != kViewCookie)
|
| return E_INVALIDARG;
|
| return E_NOTIMPL;
|
| }
|
|
|
| -STDMETHODIMP TSFTextStore::GetActiveView(TsViewCookie* view_cookie) {
|
| +STDMETHODIMP TextStore::GetActiveView(TsViewCookie* view_cookie) {
|
| if (!view_cookie)
|
| return E_INVALIDARG;
|
| // We support only one view.
|
| @@ -130,10 +134,10 @@ STDMETHODIMP TSFTextStore::GetActiveView(TsViewCookie* view_cookie) {
|
| return S_OK;
|
| }
|
|
|
| -STDMETHODIMP TSFTextStore::GetEmbedded(LONG acp_pos,
|
| - REFGUID service,
|
| - REFIID iid,
|
| - IUnknown** unknown) {
|
| +STDMETHODIMP TextStore::GetEmbedded(LONG acp_pos,
|
| + REFGUID service,
|
| + REFIID iid,
|
| + IUnknown** unknown) {
|
| // We don't support any embedded objects.
|
| NOTIMPLEMENTED();
|
| if (!unknown)
|
| @@ -142,7 +146,7 @@ STDMETHODIMP TSFTextStore::GetEmbedded(LONG acp_pos,
|
| return E_NOTIMPL;
|
| }
|
|
|
| -STDMETHODIMP TSFTextStore::GetEndACP(LONG* acp) {
|
| +STDMETHODIMP TextStore::GetEndACP(LONG* acp) {
|
| if (!acp)
|
| return E_INVALIDARG;
|
| if (!HasReadLock())
|
| @@ -151,13 +155,13 @@ STDMETHODIMP TSFTextStore::GetEndACP(LONG* acp) {
|
| return S_OK;
|
| }
|
|
|
| -STDMETHODIMP TSFTextStore::GetFormattedText(LONG acp_start, LONG acp_end,
|
| +STDMETHODIMP TextStore::GetFormattedText(LONG acp_start, LONG acp_end,
|
| IDataObject** data_object) {
|
| NOTIMPLEMENTED();
|
| return E_NOTIMPL;
|
| }
|
|
|
| -STDMETHODIMP TSFTextStore::GetScreenExt(TsViewCookie view_cookie, RECT* rect) {
|
| +STDMETHODIMP TextStore::GetScreenExt(TsViewCookie view_cookie, RECT* rect) {
|
| if (view_cookie != kViewCookie)
|
| return E_INVALIDARG;
|
| if (!rect)
|
| @@ -166,13 +170,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;
|
| @@ -190,10 +187,10 @@ STDMETHODIMP TSFTextStore::GetScreenExt(TsViewCookie view_cookie, RECT* rect) {
|
| return S_OK;
|
| }
|
|
|
| -STDMETHODIMP TSFTextStore::GetSelection(ULONG selection_index,
|
| - ULONG selection_buffer_size,
|
| - TS_SELECTION_ACP* selection_buffer,
|
| - ULONG* fetched_count) {
|
| +STDMETHODIMP TextStore::GetSelection(ULONG selection_index,
|
| + ULONG selection_buffer_size,
|
| + TS_SELECTION_ACP* selection_buffer,
|
| + ULONG* fetched_count) {
|
| if (!selection_buffer)
|
| return E_INVALIDARG;
|
| if (!fetched_count)
|
| @@ -203,8 +200,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;
|
| @@ -212,7 +209,7 @@ STDMETHODIMP TSFTextStore::GetSelection(ULONG selection_index,
|
| return S_OK;
|
| }
|
|
|
| -STDMETHODIMP TSFTextStore::GetStatus(TS_STATUS* status) {
|
| +STDMETHODIMP TextStore::GetStatus(TS_STATUS* status) {
|
| if (!status)
|
| return E_INVALIDARG;
|
|
|
| @@ -223,15 +220,15 @@ STDMETHODIMP TSFTextStore::GetStatus(TS_STATUS* status) {
|
| return S_OK;
|
| }
|
|
|
| -STDMETHODIMP TSFTextStore::GetText(LONG acp_start,
|
| - LONG acp_end,
|
| - wchar_t* text_buffer,
|
| - ULONG text_buffer_size,
|
| - ULONG* text_buffer_copied,
|
| - TS_RUNINFO* run_info_buffer,
|
| - ULONG run_info_buffer_size,
|
| - ULONG* run_info_buffer_copied,
|
| - LONG* next_acp) {
|
| +STDMETHODIMP TextStore::GetText(LONG acp_start,
|
| + LONG acp_end,
|
| + wchar_t* text_buffer,
|
| + ULONG text_buffer_size,
|
| + ULONG* text_buffer_copied,
|
| + TS_RUNINFO* run_info_buffer,
|
| + ULONG run_info_buffer_size,
|
| + ULONG* run_info_buffer_copied,
|
| + LONG* next_acp) {
|
| if (!text_buffer_copied || !run_info_buffer_copied)
|
| return E_INVALIDARG;
|
| if (!text_buffer && text_buffer_size != 0)
|
| @@ -269,15 +266,13 @@ STDMETHODIMP TSFTextStore::GetText(LONG acp_start,
|
| return S_OK;
|
| }
|
|
|
| -STDMETHODIMP TSFTextStore::GetTextExt(TsViewCookie view_cookie,
|
| - LONG acp_start,
|
| - LONG acp_end,
|
| - RECT* rect,
|
| - BOOL* clipped) {
|
| +STDMETHODIMP TextStore::GetTextExt(TsViewCookie view_cookie,
|
| + LONG acp_start,
|
| + LONG acp_end,
|
| + RECT* rect,
|
| + BOOL* clipped) {
|
| if (!rect || !clipped)
|
| return E_INVALIDARG;
|
| - if (!text_input_client_)
|
| - return E_UNEXPECTED;
|
| if (view_cookie != kViewCookie)
|
| return E_INVALIDARG;
|
| if (!HasReadLock())
|
| @@ -293,8 +288,8 @@ STDMETHODIMP TSFTextStore::GetTextExt(TsViewCookie view_cookie,
|
| // indicates a last character's one.
|
| // 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 result = {};
|
| + RECT tmp_rect = {};
|
| const uint32 start_pos = acp_start - committed_size_;
|
| const uint32 end_pos = acp_end - committed_size_;
|
|
|
| @@ -305,34 +300,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 +330,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;
|
| }
|
| @@ -354,7 +342,7 @@ STDMETHODIMP TSFTextStore::GetTextExt(TsViewCookie view_cookie,
|
| return S_OK;
|
| }
|
|
|
| -STDMETHODIMP TSFTextStore::GetWnd(TsViewCookie view_cookie,
|
| +STDMETHODIMP TextStore::GetWnd(TsViewCookie view_cookie,
|
| HWND* window_handle) {
|
| if (!window_handle)
|
| return E_INVALIDARG;
|
| @@ -364,7 +352,7 @@ STDMETHODIMP TSFTextStore::GetWnd(TsViewCookie view_cookie,
|
| return S_OK;
|
| }
|
|
|
| -STDMETHODIMP TSFTextStore::InsertEmbedded(DWORD flags,
|
| +STDMETHODIMP TextStore::InsertEmbedded(DWORD flags,
|
| LONG acp_start,
|
| LONG acp_end,
|
| IDataObject* data_object,
|
| @@ -374,7 +362,7 @@ STDMETHODIMP TSFTextStore::InsertEmbedded(DWORD flags,
|
| return E_NOTIMPL;
|
| }
|
|
|
| -STDMETHODIMP TSFTextStore::InsertEmbeddedAtSelection(DWORD flags,
|
| +STDMETHODIMP TextStore::InsertEmbeddedAtSelection(DWORD flags,
|
| IDataObject* data_object,
|
| LONG* acp_start,
|
| LONG* acp_end,
|
| @@ -384,14 +372,14 @@ STDMETHODIMP TSFTextStore::InsertEmbeddedAtSelection(DWORD flags,
|
| return E_NOTIMPL;
|
| }
|
|
|
| -STDMETHODIMP TSFTextStore::InsertTextAtSelection(DWORD flags,
|
| +STDMETHODIMP TextStore::InsertTextAtSelection(DWORD flags,
|
| const wchar_t* text_buffer,
|
| ULONG text_buffer_size,
|
| 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) {
|
| @@ -399,9 +387,8 @@ STDMETHODIMP TSFTextStore::InsertTextAtSelection(DWORD flags,
|
| return TS_E_NOLOCK;
|
| if (acp_start)
|
| *acp_start = start_pos;
|
| - if (acp_end) {
|
| + if (acp_end)
|
| *acp_end = end_pos;
|
| - }
|
| return S_OK;
|
| }
|
|
|
| @@ -423,12 +410,12 @@ 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;
|
| }
|
|
|
| -STDMETHODIMP TSFTextStore::QueryInsert(
|
| +STDMETHODIMP TextStore::QueryInsert(
|
| LONG acp_test_start,
|
| LONG acp_test_end,
|
| ULONG text_size,
|
| @@ -445,7 +432,7 @@ STDMETHODIMP TSFTextStore::QueryInsert(
|
| return S_OK;
|
| }
|
|
|
| -STDMETHODIMP TSFTextStore::QueryInsertEmbedded(const GUID* service,
|
| +STDMETHODIMP TextStore::QueryInsertEmbedded(const GUID* service,
|
| const FORMATETC* format,
|
| BOOL* insertable) {
|
| if (!format)
|
| @@ -456,7 +443,7 @@ STDMETHODIMP TSFTextStore::QueryInsertEmbedded(const GUID* service,
|
| return S_OK;
|
| }
|
|
|
| -STDMETHODIMP TSFTextStore::RequestAttrsAtPosition(
|
| +STDMETHODIMP TextStore::RequestAttrsAtPosition(
|
| LONG acp_pos,
|
| ULONG attribute_buffer_size,
|
| const TS_ATTRID* attribute_buffer,
|
| @@ -467,7 +454,7 @@ STDMETHODIMP TSFTextStore::RequestAttrsAtPosition(
|
| return S_OK;
|
| }
|
|
|
| -STDMETHODIMP TSFTextStore::RequestAttrsTransitioningAtPosition(
|
| +STDMETHODIMP TextStore::RequestAttrsTransitioningAtPosition(
|
| LONG acp_pos,
|
| ULONG attribute_buffer_size,
|
| const TS_ATTRID* attribute_buffer,
|
| @@ -478,7 +465,7 @@ STDMETHODIMP TSFTextStore::RequestAttrsTransitioningAtPosition(
|
| return S_OK;
|
| }
|
|
|
| -STDMETHODIMP TSFTextStore::RequestLock(DWORD lock_flags, HRESULT* result) {
|
| +STDMETHODIMP TextStore::RequestLock(DWORD lock_flags, HRESULT* result) {
|
| if (!text_store_acp_sink_.get())
|
| return E_FAIL;
|
| if (!result)
|
| @@ -516,12 +503,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,47 +516,42 @@ 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);
|
| - }
|
| -
|
| - // Calls TextInputClient::SetCompositionText().
|
| - CompositionText composition_text;
|
| - composition_text.text = composition_string;
|
| - composition_text.underlines = composition_undelines_;
|
| - // 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 (delegate_) {
|
| + // If there is new committed string, calls
|
| + // TextStoreDelegate::ConfirmComposition().
|
| + if ((!new_committed_string.empty()))
|
| + delegate_->OnTextCommitted(new_committed_string);
|
| +
|
| + // Calls TextInputClient::SetCompositionText().
|
| + std::vector<metro_viewer::UnderlineInfo> underlines = underlines_;
|
| + // Adjusts the offset.
|
| + 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 (text_input_client_)
|
| - text_input_client_->SetCompositionText(composition_text);
|
|
|
| // 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)
|
| text_store_acp_sink_->OnLayoutChange(TS_LC_CHANGE, 0);
|
| if (text_store_acp_sink_mask_ & TS_AS_TEXT_CHANGE) {
|
| - TS_TEXTCHANGE textChange;
|
| + TS_TEXTCHANGE textChange = {};
|
| textChange.acpStart = 0;
|
| textChange.acpOldEnd = new_committed_size;
|
| textChange.acpNewEnd = 0;
|
| @@ -580,13 +562,13 @@ STDMETHODIMP TSFTextStore::RequestLock(DWORD lock_flags, HRESULT* result) {
|
| return S_OK;
|
| }
|
|
|
| -STDMETHODIMP TSFTextStore::RequestSupportedAttrs(
|
| +STDMETHODIMP TextStore::RequestSupportedAttrs(
|
| DWORD /* flags */, // Seems that we should ignore this.
|
| ULONG attribute_buffer_size,
|
| 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) {
|
| @@ -596,33 +578,32 @@ STDMETHODIMP TSFTextStore::RequestSupportedAttrs(
|
| return E_FAIL;
|
| }
|
|
|
| -STDMETHODIMP TSFTextStore::RetrieveRequestedAttrs(
|
| +STDMETHODIMP TextStore::RetrieveRequestedAttrs(
|
| ULONG attribute_buffer_size,
|
| TS_ATTRVAL* attribute_buffer,
|
| 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_)
|
| - return E_UNEXPECTED;
|
| + if (!input_scope_)
|
| + return E_FAIL;
|
| // We support only input scope attribute.
|
| - *attribute_buffer_copied = 0;
|
| if (attribute_buffer_size == 0)
|
| return S_OK;
|
|
|
| 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_;
|
| attribute_buffer[0].varValue.punkVal->AddRef();
|
| *attribute_buffer_copied = 1;
|
| +
|
| return S_OK;
|
| }
|
|
|
| -STDMETHODIMP TSFTextStore::SetSelection(
|
| +STDMETHODIMP TextStore::SetSelection(
|
| ULONG selection_buffer_size,
|
| const TS_SELECTION_ACP* selection_buffer) {
|
| if (!HasReadWriteLock())
|
| @@ -635,18 +616,18 @@ 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;
|
| }
|
|
|
| -STDMETHODIMP TSFTextStore::SetText(DWORD flags,
|
| - LONG acp_start,
|
| - LONG acp_end,
|
| - const wchar_t* text_buffer,
|
| - ULONG text_buffer_size,
|
| - TS_TEXTCHANGE* text_change) {
|
| +STDMETHODIMP TextStore::SetText(DWORD flags,
|
| + LONG acp_start,
|
| + LONG acp_end,
|
| + const wchar_t* text_buffer,
|
| + ULONG text_buffer_size,
|
| + TS_TEXTCHANGE* text_change) {
|
| if (!HasReadWriteLock())
|
| return TS_E_NOLOCK;
|
| if (!((static_cast<LONG>(committed_size_) <= acp_start) &&
|
| @@ -655,20 +636,19 @@ STDMETHODIMP TSFTextStore::SetText(DWORD flags,
|
| return TS_E_INVALIDPOS;
|
| }
|
|
|
| - TS_SELECTION_ACP selection;
|
| + TS_SELECTION_ACP selection = {};
|
| selection.acpStart = acp_start;
|
| selection.acpEnd = acp_end;
|
| selection.style.ase = TS_AE_NONE;
|
| selection.style.fInterimChar = 0;
|
|
|
| - HRESULT ret;
|
| - ret = SetSelection(1, &selection);
|
| + HRESULT ret = SetSelection(1, &selection);
|
| if (ret != S_OK)
|
| return ret;
|
|
|
| TS_TEXTCHANGE change;
|
| - ret = InsertTextAtSelection(0, text_buffer, text_buffer_size,
|
| - &acp_start, &acp_end, &change);
|
| + ret = InsertTextAtSelection(
|
| + 0, text_buffer, text_buffer_size, &acp_start, &acp_end, &change);
|
| if (ret != S_OK)
|
| return ret;
|
|
|
| @@ -678,7 +658,7 @@ STDMETHODIMP TSFTextStore::SetText(DWORD flags,
|
| return S_OK;
|
| }
|
|
|
| -STDMETHODIMP TSFTextStore::UnadviseSink(IUnknown* unknown) {
|
| +STDMETHODIMP TextStore::UnadviseSink(IUnknown* unknown) {
|
| if (!text_store_acp_sink_.IsSameObject(unknown))
|
| return CONNECT_E_NOCONNECTION;
|
| text_store_acp_sink_.Release();
|
| @@ -686,7 +666,7 @@ STDMETHODIMP TSFTextStore::UnadviseSink(IUnknown* unknown) {
|
| return S_OK;
|
| }
|
|
|
| -STDMETHODIMP TSFTextStore::OnStartComposition(
|
| +STDMETHODIMP TextStore::OnStartComposition(
|
| ITfCompositionView* composition_view,
|
| BOOL* ok) {
|
| if (ok)
|
| @@ -694,37 +674,33 @@ STDMETHODIMP TSFTextStore::OnStartComposition(
|
| return S_OK;
|
| }
|
|
|
| -STDMETHODIMP TSFTextStore::OnUpdateComposition(
|
| +STDMETHODIMP TextStore::OnUpdateComposition(
|
| ITfCompositionView* composition_view,
|
| ITfRange* range) {
|
| return S_OK;
|
| }
|
|
|
| -STDMETHODIMP TSFTextStore::OnEndComposition(
|
| +STDMETHODIMP TextStore::OnEndComposition(
|
| ITfCompositionView* composition_view) {
|
| return S_OK;
|
| }
|
|
|
| -STDMETHODIMP TSFTextStore::OnEndEdit(ITfContext* context,
|
| - TfEditCookie read_only_edit_cookie,
|
| - ITfEditRecord* edit_record) {
|
| +STDMETHODIMP TextStore::OnEndEdit(ITfContext* context,
|
| + 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_)) {
|
| + // TODO(yukawa): Error handling.
|
| return S_OK;
|
| }
|
| - composition_undelines_ = undelines;
|
| - committed_size_ = committed_size;
|
| edit_flag_ = true;
|
| return S_OK;
|
| }
|
|
|
| -bool TSFTextStore::GetDisplayAttribute(TfGuidAtom guid_atom,
|
| - TF_DISPLAYATTRIBUTE* attribute) {
|
| +bool TextStore::GetDisplayAttribute(TfGuidAtom guid_atom,
|
| + TF_DISPLAYATTRIBUTE* attribute) {
|
| GUID guid;
|
| if (FAILED(category_manager_->GetGUID(guid_atom, &guid)))
|
| return false;
|
| @@ -737,17 +713,17 @@ bool TSFTextStore::GetDisplayAttribute(TfGuidAtom guid_atom,
|
| return SUCCEEDED(display_attribute_info->GetAttributeInfo(attribute));
|
| }
|
|
|
| -bool TSFTextStore::GetCompositionStatus(
|
| +bool TextStore::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);
|
| - const GUID* rgGuids[2] = {&GUID_PROP_COMPOSING, &GUID_PROP_ATTRIBUTE};
|
| + const GUID* kTargetGuids[2] = {&GUID_PROP_COMPOSING, &GUID_PROP_ATTRIBUTE};
|
| base::win::ScopedComPtr<ITfReadOnlyProperty> track_property;
|
| - if (FAILED(context->TrackProperties(rgGuids, 2, NULL, 0,
|
| + if (FAILED(context->TrackProperties(kTargetGuids, 2, NULL, 0,
|
| track_property.Receive()))) {
|
| return false;
|
| }
|
| @@ -786,7 +762,7 @@ bool TSFTextStore::GetCompositionStatus(
|
| if (FAILED(enum_prop_value.QueryFrom(value.AsInput()->punkVal)))
|
| return false;
|
|
|
| - TF_PROPERTYVAL property_value;
|
| + TF_PROPERTYVAL property_value = {};
|
| bool is_composition = false;
|
| bool has_display_attribute = false;
|
| TF_DISPLAYATTRIBUTE display_attribute;
|
| @@ -810,34 +786,17 @@ 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() {
|
| +bool TextStore::CancelComposition() {
|
| // If there is an on-going document lock, we must not edit the text.
|
| if (edit_flag_)
|
| return false;
|
| @@ -856,8 +815,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)
|
| @@ -872,7 +831,7 @@ bool TSFTextStore::CancelComposition() {
|
| return true;
|
| }
|
|
|
| -bool TSFTextStore::ConfirmComposition() {
|
| +bool TextStore::ConfirmComposition() {
|
| // If there is an on-going document lock, we must not edit the text.
|
| if (edit_flag_)
|
| return false;
|
| @@ -880,19 +839,19 @@ bool TSFTextStore::ConfirmComposition() {
|
| if (string_buffer_.empty())
|
| return true;
|
|
|
| - // See the comment in TSFTextStore::CancelComposition.
|
| + // See the comment in TextStore::CancelComposition.
|
| // This logic is based on the observation about how to emulate
|
| // ImmNotifyIME(NI_COMPOSITIONSTR, CPS_COMPLETE, 0) by CUAS.
|
|
|
| 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)
|
| @@ -907,17 +866,17 @@ bool TSFTextStore::ConfirmComposition() {
|
| return true;
|
| }
|
|
|
| -void TSFTextStore::SendOnLayoutChange() {
|
| +void TextStore::SendOnLayoutChange() {
|
| if (text_store_acp_sink_ && (text_store_acp_sink_mask_ & TS_AS_LAYOUT_CHANGE))
|
| text_store_acp_sink_->OnLayoutChange(TS_LC_CHANGE, 0);
|
| }
|
|
|
| -bool TSFTextStore::HasReadLock() const {
|
| +bool TextStore::HasReadLock() const {
|
| return (current_lock_type_ & TS_LF_READ) == TS_LF_READ;
|
| }
|
|
|
| -bool TSFTextStore::HasReadWriteLock() const {
|
| +bool TextStore::HasReadWriteLock() const {
|
| return (current_lock_type_ & TS_LF_READWRITE) == TS_LF_READWRITE;
|
| }
|
|
|
| -} // namespace ui
|
| +} // namespace metro_driver
|
|
|