summaryrefslogtreecommitdiffstats
path: root/chromium/ui/base/ime/win
diff options
context:
space:
mode:
authorJocelyn Turcotte <jocelyn.turcotte@digia.com>2014-08-08 14:30:41 +0200
committerJocelyn Turcotte <jocelyn.turcotte@digia.com>2014-08-12 13:49:54 +0200
commitab0a50979b9eb4dfa3320eff7e187e41efedf7a9 (patch)
tree498dfb8a97ff3361a9f7486863a52bb4e26bb898 /chromium/ui/base/ime/win
parent4ce69f7403811819800e7c5ae1318b2647e778d1 (diff)
Update Chromium to beta version 37.0.2062.68
Change-Id: I188e3b5aff1bec75566014291b654eb19f5bc8ca Reviewed-by: Andras Becsi <andras.becsi@digia.com>
Diffstat (limited to 'chromium/ui/base/ime/win')
-rw-r--r--chromium/ui/base/ime/win/imm32_manager.cc35
-rw-r--r--chromium/ui/base/ime/win/imm32_manager.h16
-rw-r--r--chromium/ui/base/ime/win/mock_tsf_bridge.cc83
-rw-r--r--chromium/ui/base/ime/win/mock_tsf_bridge.h100
-rw-r--r--chromium/ui/base/ime/win/tsf_bridge.cc558
-rw-r--r--chromium/ui/base/ime/win/tsf_bridge.h97
-rw-r--r--chromium/ui/base/ime/win/tsf_event_router.cc307
-rw-r--r--chromium/ui/base/ime/win/tsf_event_router.h81
-rw-r--r--chromium/ui/base/ime/win/tsf_input_scope.cc4
-rw-r--r--chromium/ui/base/ime/win/tsf_input_scope.h13
-rw-r--r--chromium/ui/base/ime/win/tsf_text_store.cc923
-rw-r--r--chromium/ui/base/ime/win/tsf_text_store.h297
-rw-r--r--chromium/ui/base/ime/win/tsf_text_store_unittest.cc1302
13 files changed, 32 insertions, 3784 deletions
diff --git a/chromium/ui/base/ime/win/imm32_manager.cc b/chromium/ui/base/ime/win/imm32_manager.cc
index 093b0109366..7ad2d875e4c 100644
--- a/chromium/ui/base/ime/win/imm32_manager.cc
+++ b/chromium/ui/base/ime/win/imm32_manager.cc
@@ -4,8 +4,6 @@
#include "ui/base/ime/win/imm32_manager.h"
-#include <atlbase.h>
-#include <atlcom.h>
#include <msctf.h>
#include "base/basictypes.h"
@@ -24,7 +22,7 @@
// Following code requires wchar_t to be same as char16. It should always be
// true on Windows.
-COMPILE_ASSERT(sizeof(wchar_t) == sizeof(char16), wchar_t__char16_diff);
+COMPILE_ASSERT(sizeof(wchar_t) == sizeof(base::char16), wchar_t__char16_diff);
///////////////////////////////////////////////////////////////////////////////
// IMM32Manager
@@ -85,10 +83,11 @@ void GetCompositionUnderlines(HIMC imm_context,
underline.end_offset = clause_data[i+1];
underline.color = SK_ColorBLACK;
underline.thick = false;
+ underline.background_color = SK_ColorTRANSPARENT;
// Use thick underline for the target clause.
- if (underline.start_offset >= static_cast<unsigned>(target_start) &&
- underline.end_offset <= static_cast<unsigned>(target_end)) {
+ if (underline.start_offset >= static_cast<uint32>(target_start) &&
+ underline.end_offset <= static_cast<uint32>(target_end)) {
underline.thick = true;
}
underlines->push_back(underline);
@@ -344,21 +343,22 @@ void IMM32Manager::GetCompositionInfo(HIMC imm_context, LPARAM lparam,
if (!composition->underlines.size()) {
CompositionUnderline underline;
underline.color = SK_ColorBLACK;
+ underline.background_color = SK_ColorTRANSPARENT;
if (target_start > 0) {
- underline.start_offset = 0;
- underline.end_offset = target_start;
+ underline.start_offset = 0U;
+ underline.end_offset = static_cast<uint32>(target_start);
underline.thick = false;
composition->underlines.push_back(underline);
}
if (target_end > target_start) {
- underline.start_offset = target_start;
- underline.end_offset = target_end;
+ underline.start_offset = static_cast<uint32>(target_start);
+ underline.end_offset = static_cast<uint32>(target_end);
underline.thick = true;
composition->underlines.push_back(underline);
}
if (target_end < length) {
- underline.start_offset = target_end;
- underline.end_offset = length;
+ underline.start_offset = static_cast<uint32>(target_end);
+ underline.end_offset = static_cast<uint32>(length);
underline.thick = false;
composition->underlines.push_back(underline);
}
@@ -368,7 +368,7 @@ void IMM32Manager::GetCompositionInfo(HIMC imm_context, LPARAM lparam,
bool IMM32Manager::GetString(HIMC imm_context,
WPARAM lparam,
int type,
- string16* result) {
+ base::string16* result) {
if (!(lparam & type))
return false;
LONG string_size = ::ImmGetCompositionString(imm_context, type, NULL, 0);
@@ -381,7 +381,7 @@ bool IMM32Manager::GetString(HIMC imm_context,
}
bool IMM32Manager::GetResult(
- HWND window_handle, LPARAM lparam, string16* result) {
+ HWND window_handle, LPARAM lparam, base::string16* result) {
bool ret = false;
HIMC imm_context = ::ImmGetContext(window_handle);
if (imm_context) {
@@ -487,7 +487,7 @@ std::string IMM32Manager::GetInputLanguageName() const {
return std::string();
std::string language;
- WideToUTF8(buffer, length - 1, &language);
+ base::WideToUTF8(buffer, length - 1, &language);
if (SUBLANGID(input_language_id_) == SUBLANG_NEUTRAL)
return language;
@@ -498,15 +498,10 @@ std::string IMM32Manager::GetInputLanguageName() const {
return language;
std::string region;
- WideToUTF8(buffer, length - 1, &region);
+ base::WideToUTF8(buffer, length - 1, &region);
return language.append(1, '-').append(region);
}
-base::i18n::TextDirection IMM32Manager::GetTextDirection() const {
- return IsRTLPrimaryLangID(PRIMARYLANGID(input_language_id_)) ?
- base::i18n::RIGHT_TO_LEFT : base::i18n::LEFT_TO_RIGHT;
-}
-
void IMM32Manager::SetTextInputMode(HWND window_handle,
TextInputMode input_mode) {
if (input_mode == ui::TEXT_INPUT_MODE_DEFAULT)
diff --git a/chromium/ui/base/ime/win/imm32_manager.h b/chromium/ui/base/ime/win/imm32_manager.h
index 17892cb7640..3a969fd64a6 100644
--- a/chromium/ui/base/ime/win/imm32_manager.h
+++ b/chromium/ui/base/ime/win/imm32_manager.h
@@ -14,7 +14,7 @@
#include "base/i18n/rtl.h"
#include "base/strings/string16.h"
#include "ui/base/ime/text_input_mode.h"
-#include "ui/base/ui_export.h"
+#include "ui/base/ui_base_export.h"
#include "ui/gfx/rect.h"
namespace ui {
@@ -74,7 +74,7 @@ struct CompositionText;
// hand, we can NEVER disable either TSF or CUAS in Windows Vista, i.e.
// THIS CLASS IS NOT ONLY USED ON THE INPUT CONTEXTS OF EAST-ASIAN
// LANGUAGES BUT ALSO USED ON THE INPUT CONTEXTS OF ALL LANGUAGES.
-class UI_EXPORT IMM32Manager {
+class UI_BASE_EXPORT IMM32Manager {
public:
IMM32Manager();
virtual ~IMM32Manager();
@@ -154,7 +154,7 @@ class UI_EXPORT IMM32Manager {
// the same parameter of a WM_IME_COMPOSITION message handler.
// This parameter is used for checking if the ongoing composition has
// its result string,
- // * result [out] (string16)
+ // * result [out] (base::string16)
// Represents the object contains the composition result.
// Return values
// * true
@@ -164,7 +164,7 @@ class UI_EXPORT IMM32Manager {
// Remarks
// This function is designed for being called from WM_IME_COMPOSITION
// message handlers.
- bool GetResult(HWND window_handle, LPARAM lparam, string16* result);
+ bool GetResult(HWND window_handle, LPARAM lparam, base::string16* result);
// Retrieves the current composition status of the ongoing composition.
// Parameters
@@ -237,9 +237,6 @@ class UI_EXPORT IMM32Manager {
// Returns BCP-47 tag name of the current input language.
std::string GetInputLanguageName() const;
- // Returns the text direction of the current input language.
- base::i18n::TextDirection GetTextDirection() const;
-
// Sets conversion status corresponding to |input_mode|.
virtual void SetTextInputMode(HWND window_handle, TextInputMode input_mode);
@@ -274,7 +271,10 @@ class UI_EXPORT IMM32Manager {
void CompleteComposition(HWND window_handle, HIMC imm_context);
// Retrieves a string from the IMM.
- bool GetString(HIMC imm_context, WPARAM lparam, int type, string16* result);
+ bool GetString(HIMC imm_context,
+ WPARAM lparam,
+ int type,
+ base::string16* result);
private:
// Represents whether or not there is an ongoing composition in a browser
diff --git a/chromium/ui/base/ime/win/mock_tsf_bridge.cc b/chromium/ui/base/ime/win/mock_tsf_bridge.cc
deleted file mode 100644
index a26a81b1ebb..00000000000
--- a/chromium/ui/base/ime/win/mock_tsf_bridge.cc
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright (c) 2012 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.
-
-#include "ui/base/ime/win/mock_tsf_bridge.h"
-
-#include "ui/base/ime/text_input_client.h"
-#include "base/logging.h"
-
-namespace ui {
-
-MockTSFBridge::MockTSFBridge()
- : enable_ime_call_count_(0),
- disalbe_ime_call_count_(0),
- cancel_composition_call_count_(0),
- confirm_composition_call_count_(0),
- on_text_layout_changed_(0),
- associate_focus_call_count_(0),
- set_focused_client_call_count_(0),
- remove_focused_client_call_count_(0),
- text_input_client_(NULL),
- focused_window_(NULL),
- latest_text_input_type_(TEXT_INPUT_TYPE_NONE) {
-}
-
-MockTSFBridge::~MockTSFBridge() {
-}
-
-bool MockTSFBridge::CancelComposition() {
- ++cancel_composition_call_count_;
- return true;
-}
-
-bool MockTSFBridge::ConfirmComposition() {
- ++confirm_composition_call_count_;
- return true;
-}
-
-void MockTSFBridge::OnTextInputTypeChanged(const TextInputClient* client) {
- latest_text_input_type_ = client->GetTextInputType();
-}
-
-void MockTSFBridge::OnTextLayoutChanged() {
- ++on_text_layout_changed_;
-}
-
-void MockTSFBridge::SetFocusedClient(HWND focused_window,
- TextInputClient* client) {
- ++set_focused_client_call_count_;
- focused_window_ = focused_window;
- text_input_client_ = client;
-}
-
-void MockTSFBridge::RemoveFocusedClient(TextInputClient* client) {
- ++remove_focused_client_call_count_;
- DCHECK_EQ(client, text_input_client_);
- text_input_client_ = NULL;
- focused_window_ = NULL;
-}
-
-base::win::ScopedComPtr<ITfThreadMgr> MockTSFBridge::GetThreadManager() {
- return thread_manager_;
-}
-
-TextInputClient* MockTSFBridge::GetFocusedTextInputClient() const {
- return text_input_client_;
-}
-
-void MockTSFBridge::Reset() {
- enable_ime_call_count_ = 0;
- disalbe_ime_call_count_ = 0;
- cancel_composition_call_count_ = 0;
- confirm_composition_call_count_ = 0;
- on_text_layout_changed_ = 0;
- associate_focus_call_count_ = 0;
- set_focused_client_call_count_ = 0;
- remove_focused_client_call_count_ = 0;
- text_input_client_ = NULL;
- focused_window_ = NULL;
- latest_text_input_type_ = TEXT_INPUT_TYPE_NONE;
-}
-
-} // namespace ui
diff --git a/chromium/ui/base/ime/win/mock_tsf_bridge.h b/chromium/ui/base/ime/win/mock_tsf_bridge.h
deleted file mode 100644
index 1fdfc8ae049..00000000000
--- a/chromium/ui/base/ime/win/mock_tsf_bridge.h
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright (c) 2012 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.
-
-#ifndef UI_BASE_IME_WIN_MOCK_TSF_BRIDGE_H_
-#define UI_BASE_IME_WIN_MOCK_TSF_BRIDGE_H_
-
-#include <msctf.h>
-
-#include "base/compiler_specific.h"
-#include "base/win/scoped_comptr.h"
-#include "ui/base/ime/text_input_type.h"
-#include "ui/base/ime/win/tsf_bridge.h"
-
-namespace ui {
-
-class MockTSFBridge : public TSFBridge {
- public:
- MockTSFBridge();
- virtual ~MockTSFBridge();
-
- // TSFBridge:
- virtual bool CancelComposition() OVERRIDE;
- virtual bool ConfirmComposition() OVERRIDE;
- virtual void OnTextInputTypeChanged(const TextInputClient* client) OVERRIDE;
- virtual void OnTextLayoutChanged() OVERRIDE;
- virtual void SetFocusedClient(HWND focused_window,
- TextInputClient* client) OVERRIDE;
- virtual void RemoveFocusedClient(TextInputClient* client) OVERRIDE;
- virtual base::win::ScopedComPtr<ITfThreadMgr> GetThreadManager() OVERRIDE;
- virtual TextInputClient* GetFocusedTextInputClient() const OVERRIDE;
-
- // Resets MockTSFBridge state including function call counter.
- void Reset();
-
- // Call count of EnableIME().
- int enable_ime_call_count() const { return enable_ime_call_count_; }
-
- // Call count of DisableIME().
- int disalbe_ime_call_count() const { return disalbe_ime_call_count_; }
-
- // Call count of CancelComposition().
- int cancel_composition_call_count() const {
- return cancel_composition_call_count_;
- }
-
- // Call count of ConfirmComposition().
- int confirm_composition_call_count() const {
- return confirm_composition_call_count_;
- }
-
- // Call count of OnTextLayoutChanged().
- int on_text_layout_changed() const {
- return on_text_layout_changed_;
- }
-
- // Call count of AssociateFocus().
- int associate_focus_call_count() const { return associate_focus_call_count_; }
-
- // Call count of SetFocusClient().
- int set_focused_client_call_count() const {
- return set_focused_client_call_count_;
- }
-
- // Call count of RemoveFocusedClient().
- int remove_focused_client_call_count() const {
- return remove_focused_client_call_count_;
- }
-
- // Returns current TextInputClient.
- TextInputClient* text_input_clinet() const { return text_input_client_; }
-
- // Returns currently focused window handle.
- HWND focused_window() const { return focused_window_; }
-
- // Returns latest text input type.
- TextInputType latest_text_iput_type() const {
- return latest_text_input_type_;
- }
-
- private:
- int enable_ime_call_count_;
- int disalbe_ime_call_count_;
- int cancel_composition_call_count_;
- int confirm_composition_call_count_;
- int on_text_layout_changed_;
- int associate_focus_call_count_;
- int set_focused_client_call_count_;
- int remove_focused_client_call_count_;
- TextInputClient* text_input_client_;
- HWND focused_window_;
- TextInputType latest_text_input_type_;
- base::win::ScopedComPtr<ITfThreadMgr> thread_manager_;
-
- DISALLOW_COPY_AND_ASSIGN(MockTSFBridge);
-};
-
-} // namespace ui
-
-#endif // UI_BASE_IME_WIN_MOCK_TSF_BRIDGE_H_
diff --git a/chromium/ui/base/ime/win/tsf_bridge.cc b/chromium/ui/base/ime/win/tsf_bridge.cc
deleted file mode 100644
index bf2820323ef..00000000000
--- a/chromium/ui/base/ime/win/tsf_bridge.cc
+++ /dev/null
@@ -1,558 +0,0 @@
-// Copyright (c) 2012 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.
-
-#include <msctf.h>
-
-#include <map>
-
-#include "base/logging.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop.h"
-#include "base/threading/thread_local_storage.h"
-#include "base/win/scoped_comptr.h"
-#include "base/win/scoped_variant.h"
-#include "ui/base/ime/text_input_client.h"
-#include "ui/base/ime/win/tsf_bridge.h"
-#include "ui/base/ime/win/tsf_text_store.h"
-
-namespace ui {
-
-namespace {
-
-// We use thread local storage for TSFBridge lifespan management.
-base::ThreadLocalStorage::StaticSlot tls_tsf_bridge = TLS_INITIALIZER;
-
-
-// TsfBridgeDelegate -----------------------------------------------------------
-
-// A TLS implementation of TSFBridge.
-class TSFBridgeDelegate : public TSFBridge {
- public:
- TSFBridgeDelegate();
- virtual ~TSFBridgeDelegate();
-
- bool Initialize();
-
- // TsfBridge:
- virtual void OnTextInputTypeChanged(const TextInputClient* client) OVERRIDE;
- virtual void OnTextLayoutChanged() OVERRIDE;
- virtual bool CancelComposition() OVERRIDE;
- virtual bool ConfirmComposition() OVERRIDE;
- virtual void SetFocusedClient(HWND focused_window,
- TextInputClient* client) OVERRIDE;
- virtual void RemoveFocusedClient(TextInputClient* client) OVERRIDE;
- virtual base::win::ScopedComPtr<ITfThreadMgr> GetThreadManager() OVERRIDE;
- virtual TextInputClient* GetFocusedTextInputClient() const OVERRIDE;
-
- private:
- // Returns true if |tsf_document_map_| is successfully initialized. This
- // method should be called from and only from Initialize().
- bool InitializeDocumentMapInternal();
-
- // Returns true if |context| is successfully updated to be a disabled
- // context, where an IME should be deactivated. This is suitable for some
- // special input context such as password fields.
- bool InitializeDisabledContext(ITfContext* context);
-
- // Returns true if a TSF document manager and a TSF context is successfully
- // created with associating with given |text_store|. The returned
- // |source_cookie| indicates the binding between |text_store| and |context|.
- // You can pass NULL to |text_store| and |source_cookie| when text store is
- // not necessary.
- bool CreateDocumentManager(TSFTextStore* text_store,
- ITfDocumentMgr** document_manager,
- ITfContext** context,
- DWORD* source_cookie);
-
- // Returns true if |document_manager| is the focused document manager.
- bool IsFocused(ITfDocumentMgr* document_manager);
-
- // Returns true if already initialized.
- bool IsInitialized();
-
- // Updates or clears the association maintained in the TSF runtime between
- // |attached_window_handle_| and the current document manager. Keeping this
- // association updated solves some tricky event ordering issues between
- // logical text input focus managed by Chrome and native text input focus
- // managed by the OS.
- // Background:
- // TSF runtime monitors some Win32 messages such as WM_ACTIVATE to
- // change the focused document manager. This is problematic when
- // TSFBridge::SetFocusedClient is called first then the target window
- // receives WM_ACTIVATE. This actually occurs in Aura environment where
- // WM_NCACTIVATE is used as a trigger to restore text input focus.
- // Caveats:
- // TSF runtime does not increment the reference count of the attached
- // document manager. See the comment inside the method body for
- // details.
- void UpdateAssociateFocus();
- void ClearAssociateFocus();
-
- // A triple of document manager, text store and binding cookie between
- // a context owned by the document manager and the text store. This is a
- // minimum working set of an editable document in TSF.
- struct TSFDocument {
- public:
- TSFDocument() : cookie(TF_INVALID_COOKIE) {}
- TSFDocument(const TSFDocument& src)
- : document_manager(src.document_manager),
- cookie(src.cookie) {}
- base::win::ScopedComPtr<ITfDocumentMgr> document_manager;
- scoped_refptr<TSFTextStore> text_store;
- DWORD cookie;
- };
-
- // Returns a pointer to TSFDocument that is associated with the current
- // TextInputType of |client_|.
- TSFDocument* GetAssociatedDocument();
-
- // An ITfThreadMgr object to be used in focus and document management.
- base::win::ScopedComPtr<ITfThreadMgr> thread_manager_;
-
- // A map from TextInputType to an editable document for TSF. We use multiple
- // TSF documents that have different InputScopes and TSF attributes based on
- // the TextInputType associated with the target document. For a TextInputType
- // that is not coverted by this map, a default document, e.g. the document
- // for TEXT_INPUT_TYPE_TEXT, should be used.
- // Note that some IMEs don't change their state unless the document focus is
- // changed. This is why we use multiple documents instead of changing TSF
- // metadata of a single document on the fly.
- typedef std::map<TextInputType, TSFDocument> TSFDocumentMap;
- TSFDocumentMap tsf_document_map_;
-
- // An identifier of TSF client.
- TfClientId client_id_;
-
- // Current focused text input client. Do not free |client_|.
- TextInputClient* client_;
-
- // Represents the window that is currently owns text input focus.
- HWND attached_window_handle_;
-
- DISALLOW_COPY_AND_ASSIGN(TSFBridgeDelegate);
-};
-
-TSFBridgeDelegate::TSFBridgeDelegate()
- : client_id_(TF_CLIENTID_NULL),
- client_(NULL),
- attached_window_handle_(NULL) {
-}
-
-TSFBridgeDelegate::~TSFBridgeDelegate() {
- DCHECK_EQ(base::MessageLoop::TYPE_UI, base::MessageLoop::current()->type());
- if (!IsInitialized())
- return;
- for (TSFDocumentMap::iterator it = tsf_document_map_.begin();
- it != tsf_document_map_.end(); ++it) {
- base::win::ScopedComPtr<ITfContext> context;
- base::win::ScopedComPtr<ITfSource> source;
- if (it->second.cookie != TF_INVALID_COOKIE &&
- SUCCEEDED(it->second.document_manager->GetBase(context.Receive())) &&
- SUCCEEDED(source.QueryFrom(context))) {
- source->UnadviseSink(it->second.cookie);
- }
- }
- tsf_document_map_.clear();
-
- client_id_ = TF_CLIENTID_NULL;
-}
-
-bool TSFBridgeDelegate::Initialize() {
- DCHECK_EQ(base::MessageLoop::TYPE_UI, base::MessageLoop::current()->type());
- if (client_id_ != TF_CLIENTID_NULL) {
- DVLOG(1) << "Already initialized.";
- return false;
- }
-
- if (FAILED(thread_manager_.CreateInstance(CLSID_TF_ThreadMgr))) {
- DVLOG(1) << "Failed to create ThreadManager instance.";
- return false;
- }
-
- if (FAILED(thread_manager_->Activate(&client_id_))) {
- DVLOG(1) << "Failed to activate Thread Manager.";
- return false;
- }
-
- if (!InitializeDocumentMapInternal())
- return false;
-
- // Japanese IME expects the default value of this compartment is
- // TF_SENTENCEMODE_PHRASEPREDICT like IMM32 implementation. This value is
- // managed per thread, so that it is enough to set this value at once. This
- // value does not affect other language's IME behaviors.
- base::win::ScopedComPtr<ITfCompartmentMgr> thread_compartment_manager;
- if (FAILED(thread_compartment_manager.QueryFrom(thread_manager_))) {
- DVLOG(1) << "Failed to get ITfCompartmentMgr.";
- return false;
- }
-
- base::win::ScopedComPtr<ITfCompartment> sentence_compartment;
- if (FAILED(thread_compartment_manager->GetCompartment(
- GUID_COMPARTMENT_KEYBOARD_INPUTMODE_SENTENCE,
- sentence_compartment.Receive()))) {
- DVLOG(1) << "Failed to get sentence compartment.";
- return false;
- }
-
- base::win::ScopedVariant sentence_variant;
- sentence_variant.Set(TF_SENTENCEMODE_PHRASEPREDICT);
- if (FAILED(sentence_compartment->SetValue(client_id_, &sentence_variant))) {
- DVLOG(1) << "Failed to change the sentence mode.";
- return false;
- }
-
- return true;
-}
-
-void TSFBridgeDelegate::OnTextInputTypeChanged(const TextInputClient* client) {
- DCHECK_EQ(base::MessageLoop::TYPE_UI, base::MessageLoop::current()->type());
- DCHECK(IsInitialized());
-
- if (client != client_) {
- // Called from not focusing client. Do nothing.
- return;
- }
-
- UpdateAssociateFocus();
-
- TSFDocument* document = GetAssociatedDocument();
- if (!document)
- return;
- thread_manager_->SetFocus(document->document_manager.get());
- OnTextLayoutChanged();
-}
-
-void TSFBridgeDelegate::OnTextLayoutChanged() {
- TSFDocument* document = GetAssociatedDocument();
- if (!document)
- return;
- if (!document->text_store)
- return;
- document->text_store->SendOnLayoutChange();
-}
-
-bool TSFBridgeDelegate::CancelComposition() {
- DCHECK_EQ(base::MessageLoop::TYPE_UI, base::MessageLoop::current()->type());
- DCHECK(IsInitialized());
-
- TSFDocument* document = GetAssociatedDocument();
- if (!document)
- return false;
- if (!document->text_store)
- return false;
-
- return document->text_store->CancelComposition();
-}
-
-bool TSFBridgeDelegate::ConfirmComposition() {
- DCHECK_EQ(base::MessageLoop::TYPE_UI, base::MessageLoop::current()->type());
- DCHECK(IsInitialized());
-
- TSFDocument* document = GetAssociatedDocument();
- if (!document)
- return false;
- if (!document->text_store)
- return false;
-
- return document->text_store->ConfirmComposition();
-}
-
-void TSFBridgeDelegate::SetFocusedClient(HWND focused_window,
- TextInputClient* client) {
- DCHECK_EQ(base::MessageLoop::TYPE_UI, base::MessageLoop::current()->type());
- DCHECK(client);
- DCHECK(IsInitialized());
- if (attached_window_handle_ != focused_window)
- ClearAssociateFocus();
- client_ = client;
- attached_window_handle_ = focused_window;
-
- for (TSFDocumentMap::iterator it = tsf_document_map_.begin();
- it != tsf_document_map_.end(); ++it) {
- if (it->second.text_store.get() == NULL)
- continue;
- it->second.text_store->SetFocusedTextInputClient(focused_window,
- client);
- }
-
- // Synchronize text input type state.
- OnTextInputTypeChanged(client);
-}
-
-void TSFBridgeDelegate::RemoveFocusedClient(TextInputClient* client) {
- DCHECK_EQ(base::MessageLoop::TYPE_UI, base::MessageLoop::current()->type());
- DCHECK(IsInitialized());
- if (client_ != client)
- return;
- ClearAssociateFocus();
- client_ = NULL;
- attached_window_handle_ = NULL;
- for (TSFDocumentMap::iterator it = tsf_document_map_.begin();
- it != tsf_document_map_.end(); ++it) {
- if (it->second.text_store.get() == NULL)
- continue;
- it->second.text_store->SetFocusedTextInputClient(NULL, NULL);
- }
-}
-
-TextInputClient* TSFBridgeDelegate::GetFocusedTextInputClient() const {
- return client_;
-}
-
-base::win::ScopedComPtr<ITfThreadMgr> TSFBridgeDelegate::GetThreadManager() {
- DCHECK_EQ(base::MessageLoop::TYPE_UI, base::MessageLoop::current()->type());
- DCHECK(IsInitialized());
- return thread_manager_;
-}
-
-bool TSFBridgeDelegate::CreateDocumentManager(TSFTextStore* text_store,
- ITfDocumentMgr** document_manager,
- ITfContext** context,
- DWORD* source_cookie) {
- if (FAILED(thread_manager_->CreateDocumentMgr(document_manager))) {
- DVLOG(1) << "Failed to create Document Manager.";
- return false;
- }
-
- DWORD edit_cookie = TF_INVALID_EDIT_COOKIE;
- if (FAILED((*document_manager)->CreateContext(
- client_id_,
- 0,
- static_cast<ITextStoreACP*>(text_store),
- context,
- &edit_cookie))) {
- DVLOG(1) << "Failed to create Context.";
- return false;
- }
-
- if (FAILED((*document_manager)->Push(*context))) {
- DVLOG(1) << "Failed to push context.";
- return false;
- }
-
- if (!text_store || !source_cookie)
- return true;
-
- base::win::ScopedComPtr<ITfSource> source;
- if (FAILED(source.QueryFrom(*context))) {
- DVLOG(1) << "Failed to get source.";
- return false;
- }
-
- if (FAILED(source->AdviseSink(IID_ITfTextEditSink,
- static_cast<ITfTextEditSink*>(text_store),
- source_cookie))) {
- DVLOG(1) << "AdviseSink failed.";
- return false;
- }
-
- if (*source_cookie == TF_INVALID_COOKIE) {
- DVLOG(1) << "The result of cookie is invalid.";
- return false;
- }
- return true;
-}
-
-bool TSFBridgeDelegate::InitializeDocumentMapInternal() {
- const TextInputType kTextInputTypes[] = {
- TEXT_INPUT_TYPE_NONE,
- TEXT_INPUT_TYPE_TEXT,
- TEXT_INPUT_TYPE_PASSWORD,
- TEXT_INPUT_TYPE_SEARCH,
- TEXT_INPUT_TYPE_EMAIL,
- TEXT_INPUT_TYPE_NUMBER,
- TEXT_INPUT_TYPE_TELEPHONE,
- TEXT_INPUT_TYPE_URL,
- };
- for (size_t i = 0; i < arraysize(kTextInputTypes); ++i) {
- const TextInputType input_type = kTextInputTypes[i];
- base::win::ScopedComPtr<ITfContext> context;
- base::win::ScopedComPtr<ITfDocumentMgr> document_manager;
- DWORD cookie = TF_INVALID_COOKIE;
- const bool use_null_text_store = (input_type == TEXT_INPUT_TYPE_NONE);
- DWORD* cookie_ptr = use_null_text_store ? NULL : &cookie;
- scoped_refptr<TSFTextStore> text_store =
- use_null_text_store ? NULL : new TSFTextStore();
- if (!CreateDocumentManager(text_store,
- document_manager.Receive(),
- context.Receive(),
- cookie_ptr))
- return false;
- const bool use_disabled_context =
- (input_type == TEXT_INPUT_TYPE_PASSWORD ||
- input_type == TEXT_INPUT_TYPE_NONE);
- if (use_disabled_context && !InitializeDisabledContext(context))
- return false;
- tsf_document_map_[input_type].text_store = text_store;
- tsf_document_map_[input_type].document_manager = document_manager;
- tsf_document_map_[input_type].cookie = cookie;
- }
- return true;
-}
-
-bool TSFBridgeDelegate::InitializeDisabledContext(ITfContext* context) {
- base::win::ScopedComPtr<ITfCompartmentMgr> compartment_mgr;
- if (FAILED(compartment_mgr.QueryFrom(context))) {
- DVLOG(1) << "Failed to get CompartmentMgr.";
- return false;
- }
-
- base::win::ScopedComPtr<ITfCompartment> disabled_compartment;
- if (FAILED(compartment_mgr->GetCompartment(
- GUID_COMPARTMENT_KEYBOARD_DISABLED,
- disabled_compartment.Receive()))) {
- DVLOG(1) << "Failed to get keyboard disabled compartment.";
- return false;
- }
-
- base::win::ScopedVariant variant;
- variant.Set(1);
- if (FAILED(disabled_compartment->SetValue(client_id_, &variant))) {
- DVLOG(1) << "Failed to disable the DocumentMgr.";
- return false;
- }
-
- base::win::ScopedComPtr<ITfCompartment> empty_context;
- if (FAILED(compartment_mgr->GetCompartment(GUID_COMPARTMENT_EMPTYCONTEXT,
- empty_context.Receive()))) {
- DVLOG(1) << "Failed to get empty context compartment.";
- return false;
- }
- base::win::ScopedVariant empty_context_variant;
- empty_context_variant.Set(static_cast<int32>(1));
- if (FAILED(empty_context->SetValue(client_id_, &empty_context_variant))) {
- DVLOG(1) << "Failed to set empty context.";
- return false;
- }
-
- return true;
-}
-
-bool TSFBridgeDelegate::IsFocused(ITfDocumentMgr* document_manager) {
- base::win::ScopedComPtr<ITfDocumentMgr> focused_document_manager;
- if (FAILED(thread_manager_->GetFocus(focused_document_manager.Receive())))
- return false;
- return focused_document_manager.IsSameObject(document_manager);
-}
-
-bool TSFBridgeDelegate::IsInitialized() {
- return client_id_ != TF_CLIENTID_NULL;
-}
-
-void TSFBridgeDelegate::UpdateAssociateFocus() {
- if (attached_window_handle_ == NULL)
- return;
- TSFDocument* document = GetAssociatedDocument();
- if (document == NULL) {
- ClearAssociateFocus();
- return;
- }
- // NOTE: ITfThreadMgr::AssociateFocus does not increment the ref count of
- // the document manager to be attached. It is our responsibility to make sure
- // the attached document manager will not be destroyed while it is attached.
- // This should be true as long as TSFBridge::Shutdown() is called late phase
- // of UI thread shutdown.
- base::win::ScopedComPtr<ITfDocumentMgr> previous_focus;
- thread_manager_->AssociateFocus(
- attached_window_handle_, document->document_manager.get(),
- previous_focus.Receive());
-}
-
-void TSFBridgeDelegate::ClearAssociateFocus() {
- if (attached_window_handle_ == NULL)
- return;
- base::win::ScopedComPtr<ITfDocumentMgr> previous_focus;
- thread_manager_->AssociateFocus(
- attached_window_handle_, NULL, previous_focus.Receive());
-}
-
-TSFBridgeDelegate::TSFDocument* TSFBridgeDelegate::GetAssociatedDocument() {
- if (!client_)
- return NULL;
- TSFDocumentMap::iterator it =
- tsf_document_map_.find(client_->GetTextInputType());
- if (it == tsf_document_map_.end()) {
- it = tsf_document_map_.find(TEXT_INPUT_TYPE_TEXT);
- // This check is necessary because it's possible that we failed to
- // initialize |tsf_document_map_| and it has no TEXT_INPUT_TYPE_TEXT.
- if (it == tsf_document_map_.end())
- return NULL;
- }
- return &it->second;
-}
-
-} // namespace
-
-
-// TsfBridge -----------------------------------------------------------------
-
-TSFBridge::TSFBridge() {
-}
-
-TSFBridge::~TSFBridge() {
-}
-
-// static
-bool TSFBridge::Initialize() {
- if (base::MessageLoop::current()->type() != base::MessageLoop::TYPE_UI) {
- DVLOG(1) << "Do not use TSFBridge without UI thread.";
- return false;
- }
- if (!tls_tsf_bridge.initialized()) {
- tls_tsf_bridge.Initialize(TSFBridge::Finalize);
- }
- TSFBridgeDelegate* delegate =
- static_cast<TSFBridgeDelegate*>(tls_tsf_bridge.Get());
- if (delegate)
- return true;
- delegate = new TSFBridgeDelegate();
- tls_tsf_bridge.Set(delegate);
- return delegate->Initialize();
-}
-
-// static
-TSFBridge* TSFBridge::ReplaceForTesting(TSFBridge* bridge) {
- if (base::MessageLoop::current()->type() != base::MessageLoop::TYPE_UI) {
- DVLOG(1) << "Do not use TSFBridge without UI thread.";
- return NULL;
- }
- TSFBridge* old_bridge = TSFBridge::GetInstance();
- tls_tsf_bridge.Set(bridge);
- return old_bridge;
-}
-
-// static
-void TSFBridge::Shutdown() {
- if (base::MessageLoop::current()->type() != base::MessageLoop::TYPE_UI) {
- DVLOG(1) << "Do not use TSFBridge without UI thread.";
- }
- if (tls_tsf_bridge.initialized()) {
- TSFBridgeDelegate* delegate =
- static_cast<TSFBridgeDelegate*>(tls_tsf_bridge.Get());
- tls_tsf_bridge.Set(NULL);
- delete delegate;
- }
-}
-
-// static
-TSFBridge* TSFBridge::GetInstance() {
- if (base::MessageLoop::current()->type() != base::MessageLoop::TYPE_UI) {
- DVLOG(1) << "Do not use TSFBridge without UI thread.";
- return NULL;
- }
- TSFBridgeDelegate* delegate =
- static_cast<TSFBridgeDelegate*>(tls_tsf_bridge.Get());
- DCHECK(delegate) << "Do no call GetInstance before TSFBridge::Initialize.";
- return delegate;
-}
-
-// static
-void TSFBridge::Finalize(void* data) {
- TSFBridgeDelegate* delegate = static_cast<TSFBridgeDelegate*>(data);
- delete delegate;
-}
-
-} // namespace ui
diff --git a/chromium/ui/base/ime/win/tsf_bridge.h b/chromium/ui/base/ime/win/tsf_bridge.h
deleted file mode 100644
index 6256fac166a..00000000000
--- a/chromium/ui/base/ime/win/tsf_bridge.h
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright (c) 2012 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.
-
-#ifndef UI_BASE_IME_WIN_TSF_BRIDGE_H_
-#define UI_BASE_IME_WIN_TSF_BRIDGE_H_
-
-#include <Windows.h>
-#include <msctf.h>
-
-#include "base/basictypes.h"
-#include "base/win/scoped_comptr.h"
-#include "ui/base/ui_export.h"
-
-namespace ui {
-class TextInputClient;
-
-// TSFBridge provides high level IME related operations on top of Text Services
-// Framework (TSF). TSFBridge is managed by TLS because TSF related stuff is
-// associated with each thread and not allowed to access across thread boundary.
-// To be consistent with IMM32 behavior, TSFBridge is shared in the same thread.
-// TSFBridge is used by the web content text inputting field, for example
-// DisableIME() should be called if a password field is focused.
-//
-// TSFBridge also manages connectivity between TSFTextStore which is the backend
-// of text inputting and current focused TextInputClient.
-//
-// All methods in this class must be used in UI thread.
-class UI_EXPORT TSFBridge {
- public:
- virtual ~TSFBridge();
-
- // Returns the thread local TSFBridge instance. Initialize() must be called
- // first. Do not cache this pointer and use it after TSFBridge Shutdown().
- static TSFBridge* GetInstance();
-
- // Sets the thread local instance. Must be called before any calls to
- // GetInstance().
- static bool Initialize();
-
- // Injects an alternative TSFBridge such as MockTSFBridge for testing. The
- // injected object should be released by the caller. This function returns
- // previous TSFBridge pointer with ownership.
- static TSFBridge* ReplaceForTesting(TSFBridge* bridge);
-
- // Destroys the thread local instance.
- static void Shutdown();
-
- // Handles TextInputTypeChanged event. RWHVW is responsible for calling this
- // handler whenever renderer's input text type is changed. Does nothing
- // unless |client| is focused.
- virtual void OnTextInputTypeChanged(const TextInputClient* client) = 0;
-
- // Sends an event to TSF manager that the text layout should be updated.
- virtual void OnTextLayoutChanged() = 0;
-
- // Cancels the ongoing composition if exists.
- // Returns true if there is no composition.
- // Returns false if an edit session is on-going.
- // Returns false if an error occures.
- virtual bool CancelComposition() = 0;
-
- // Confirms the ongoing composition if exists.
- // Returns true if there is no composition.
- // Returns false if an edit session is on-going.
- // Returns false if an error occures.
- virtual bool ConfirmComposition() = 0;
-
- // Sets currently focused TextInputClient.
- // Caller must free |client|.
- virtual void SetFocusedClient(HWND focused_window,
- TextInputClient* client) = 0;
-
- // Removes currently focused TextInputClient.
- // Caller must free |client|.
- virtual void RemoveFocusedClient(TextInputClient* client) = 0;
-
- // Obtains current thread manager.
- virtual base::win::ScopedComPtr<ITfThreadMgr> GetThreadManager() = 0;
-
- // Returns the focused text input client.
- virtual TextInputClient* GetFocusedTextInputClient() const = 0;
-
- protected:
- // Uses GetInstance() instead.
- TSFBridge();
-
- private:
- // Releases TLS instance.
- static void Finalize(void* data);
-
- DISALLOW_COPY_AND_ASSIGN(TSFBridge);
-};
-
-} // namespace ui
-
-#endif // UI_BASE_IME_WIN_TSF_BRIDGE_H_
diff --git a/chromium/ui/base/ime/win/tsf_event_router.cc b/chromium/ui/base/ime/win/tsf_event_router.cc
deleted file mode 100644
index 4f34a048eec..00000000000
--- a/chromium/ui/base/ime/win/tsf_event_router.cc
+++ /dev/null
@@ -1,307 +0,0 @@
-// Copyright (c) 2012 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.
-
-#include "ui/base/ime/win/tsf_event_router.h"
-
-#include <msctf.h>
-#include <set>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/win/scoped_comptr.h"
-#include "base/win/metro.h"
-#include "ui/base/win/atl_module.h"
-#include "ui/gfx/range/range.h"
-
-namespace ui {
-
-
-// TSFEventRouter::Delegate ------------------------------------
-
-// The implementation class of ITfUIElementSink, whose member functions will be
-// called back by TSF when the UI element status is changed, for example when
-// the candidate window is opened or closed. This class also implements
-// ITfTextEditSink, whose member function is called back by TSF when the text
-// editting session is finished.
-class ATL_NO_VTABLE TSFEventRouter::Delegate
- : public ATL::CComObjectRootEx<CComSingleThreadModel>,
- public ITfUIElementSink,
- public ITfTextEditSink {
- public:
- BEGIN_COM_MAP(Delegate)
- COM_INTERFACE_ENTRY(ITfUIElementSink)
- COM_INTERFACE_ENTRY(ITfTextEditSink)
- END_COM_MAP()
-
- Delegate();
- ~Delegate();
-
- // ITfTextEditSink:
- STDMETHOD(OnEndEdit)(ITfContext* context, TfEditCookie read_only_cookie,
- ITfEditRecord* edit_record) OVERRIDE;
-
- // ITfUiElementSink:
- STDMETHOD(BeginUIElement)(DWORD element_id, BOOL* is_show) OVERRIDE;
- STDMETHOD(UpdateUIElement)(DWORD element_id) OVERRIDE;
- STDMETHOD(EndUIElement)(DWORD element_id) OVERRIDE;
-
- // Sets |thread_manager| to be monitored. |thread_manager| can be NULL.
- void SetManager(ITfThreadMgr* thread_manager);
-
- // Returns true if the IME is composing text.
- bool IsImeComposing();
-
- // Sets |router| to be forwarded TSF-related events.
- void SetRouter(TSFEventRouter* router);
-
- private:
- // Returns current composition range. Returns gfx::Range::InvalidRange if
- // there is no composition.
- static gfx::Range GetCompositionRange(ITfContext* context);
-
- // Returns true if the given |element_id| represents the candidate window.
- bool IsCandidateWindowInternal(DWORD element_id);
-
- // A context associated with this class.
- base::win::ScopedComPtr<ITfContext> context_;
-
- // The ITfSource associated with |context_|.
- base::win::ScopedComPtr<ITfSource> context_source_;
-
- // The cookie for |context_source_|.
- DWORD context_source_cookie_;
-
- // A UIElementMgr associated with this class.
- base::win::ScopedComPtr<ITfUIElementMgr> ui_element_manager_;
-
- // The ITfSouce associated with |ui_element_manager_|.
- base::win::ScopedComPtr<ITfSource> ui_source_;
-
- // The set of currently opened candidate window ids.
- std::set<DWORD> open_candidate_window_ids_;
-
- // The cookie for |ui_source_|.
- DWORD ui_source_cookie_;
-
- TSFEventRouter* router_;
- gfx::Range previous_composition_range_;
-
- DISALLOW_COPY_AND_ASSIGN(Delegate);
-};
-
-TSFEventRouter::Delegate::Delegate()
- : context_source_cookie_(TF_INVALID_COOKIE),
- ui_source_cookie_(TF_INVALID_COOKIE),
- router_(NULL),
- previous_composition_range_(gfx::Range::InvalidRange()) {
-}
-
-TSFEventRouter::Delegate::~Delegate() {}
-
-void TSFEventRouter::Delegate::SetRouter(TSFEventRouter* router) {
- router_ = router;
-}
-
-STDMETHODIMP TSFEventRouter::Delegate::OnEndEdit(ITfContext* context,
- TfEditCookie read_only_cookie,
- ITfEditRecord* edit_record) {
- if (!edit_record || !context)
- return E_INVALIDARG;
- if (!router_)
- return S_OK;
-
- // |edit_record| can be used to obtain updated ranges in terms of text
- // contents and/or text attributes. Here we are interested only in text update
- // so we use TF_GTP_INCL_TEXT and check if there is any range which contains
- // updated text.
- base::win::ScopedComPtr<IEnumTfRanges> ranges;
- if (FAILED(edit_record->GetTextAndPropertyUpdates(TF_GTP_INCL_TEXT, NULL, 0,
- ranges.Receive())))
- return S_OK; // Don't care about failures.
-
- ULONG fetched_count = 0;
- base::win::ScopedComPtr<ITfRange> range;
- if (FAILED(ranges->Next(1, range.Receive(), &fetched_count)))
- return S_OK; // Don't care about failures.
-
- const gfx::Range composition_range = GetCompositionRange(context);
-
- if (!previous_composition_range_.IsValid() && composition_range.IsValid())
- router_->OnTSFStartComposition();
-
- // |fetched_count| != 0 means there is at least one range that contains
- // updated text.
- if (fetched_count != 0)
- router_->OnTextUpdated(composition_range);
-
- if (previous_composition_range_.IsValid() && !composition_range.IsValid())
- router_->OnTSFEndComposition();
-
- previous_composition_range_ = composition_range;
- return S_OK;
-}
-
-STDMETHODIMP TSFEventRouter::Delegate::BeginUIElement(DWORD element_id,
- BOOL* is_show) {
- if (is_show)
- *is_show = TRUE; // Without this the UI element will not be shown.
-
- if (!IsCandidateWindowInternal(element_id))
- return S_OK;
-
- std::pair<std::set<DWORD>::iterator, bool> insert_result =
- open_candidate_window_ids_.insert(element_id);
- // Don't call if |router_| is null or |element_id| is already handled.
- if (router_ && insert_result.second)
- router_->OnCandidateWindowCountChanged(open_candidate_window_ids_.size());
-
- return S_OK;
-}
-
-STDMETHODIMP TSFEventRouter::Delegate::UpdateUIElement(
- DWORD element_id) {
- return S_OK;
-}
-
-STDMETHODIMP TSFEventRouter::Delegate::EndUIElement(
- DWORD element_id) {
- if ((open_candidate_window_ids_.erase(element_id) != 0) && router_)
- router_->OnCandidateWindowCountChanged(open_candidate_window_ids_.size());
- return S_OK;
-}
-
-void TSFEventRouter::Delegate::SetManager(
- ITfThreadMgr* thread_manager) {
- context_.Release();
-
- if (context_source_) {
- context_source_->UnadviseSink(context_source_cookie_);
- context_source_.Release();
- }
- context_source_cookie_ = TF_INVALID_COOKIE;
-
- ui_element_manager_.Release();
- if (ui_source_) {
- ui_source_->UnadviseSink(ui_source_cookie_);
- ui_source_.Release();
- }
- ui_source_cookie_ = TF_INVALID_COOKIE;
-
- if (!thread_manager)
- return;
-
- base::win::ScopedComPtr<ITfDocumentMgr> document_manager;
- if (FAILED(thread_manager->GetFocus(document_manager.Receive())) ||
- !document_manager.get() ||
- FAILED(document_manager->GetBase(context_.Receive())) ||
- FAILED(context_source_.QueryFrom(context_)))
- return;
- context_source_->AdviseSink(IID_ITfTextEditSink,
- static_cast<ITfTextEditSink*>(this),
- &context_source_cookie_);
-
- if (FAILED(ui_element_manager_.QueryFrom(thread_manager)) ||
- FAILED(ui_source_.QueryFrom(ui_element_manager_)))
- return;
- ui_source_->AdviseSink(IID_ITfUIElementSink,
- static_cast<ITfUIElementSink*>(this),
- &ui_source_cookie_);
-}
-
-bool TSFEventRouter::Delegate::IsImeComposing() {
- return context_ && GetCompositionRange(context_).IsValid();
-}
-
-// static
-gfx::Range TSFEventRouter::Delegate::GetCompositionRange(
- ITfContext* context) {
- DCHECK(context);
- base::win::ScopedComPtr<ITfContextComposition> context_composition;
- if (FAILED(context_composition.QueryFrom(context)))
- return gfx::Range::InvalidRange();
- base::win::ScopedComPtr<IEnumITfCompositionView> enum_composition_view;
- if (FAILED(context_composition->EnumCompositions(
- enum_composition_view.Receive())))
- return gfx::Range::InvalidRange();
- base::win::ScopedComPtr<ITfCompositionView> composition_view;
- if (enum_composition_view->Next(1, composition_view.Receive(),
- NULL) != S_OK)
- return gfx::Range::InvalidRange();
-
- base::win::ScopedComPtr<ITfRange> range;
- if (FAILED(composition_view->GetRange(range.Receive())))
- return gfx::Range::InvalidRange();
-
- base::win::ScopedComPtr<ITfRangeACP> range_acp;
- if (FAILED(range_acp.QueryFrom(range)))
- return gfx::Range::InvalidRange();
-
- LONG start = 0;
- LONG length = 0;
- if (FAILED(range_acp->GetExtent(&start, &length)))
- return gfx::Range::InvalidRange();
-
- return gfx::Range(start, start + length);
-}
-
-bool TSFEventRouter::Delegate::IsCandidateWindowInternal(DWORD element_id) {
- DCHECK(ui_element_manager_.get());
- base::win::ScopedComPtr<ITfUIElement> ui_element;
- if (FAILED(ui_element_manager_->GetUIElement(element_id,
- ui_element.Receive())))
- return false;
- base::win::ScopedComPtr<ITfCandidateListUIElement> candidate_list_ui_element;
- return SUCCEEDED(candidate_list_ui_element.QueryFrom(ui_element));
-}
-
-
-// TSFEventRouter ------------------------------------------------------------
-
-TSFEventRouter::TSFEventRouter(TSFEventRouterObserver* observer)
- : observer_(observer),
- delegate_(NULL) {
- DCHECK(base::win::IsTSFAwareRequired())
- << "Do not use TSFEventRouter without TSF environment.";
- DCHECK(observer_);
- CComObject<Delegate>* delegate;
- ui::win::CreateATLModuleIfNeeded();
- if (SUCCEEDED(CComObject<Delegate>::CreateInstance(&delegate))) {
- delegate->AddRef();
- delegate_.Attach(delegate);
- delegate_->SetRouter(this);
- }
-}
-
-TSFEventRouter::~TSFEventRouter() {
- if (delegate_) {
- delegate_->SetManager(NULL);
- delegate_->SetRouter(NULL);
- }
-}
-
-bool TSFEventRouter::IsImeComposing() {
- return delegate_->IsImeComposing();
-}
-
-void TSFEventRouter::OnCandidateWindowCountChanged(size_t window_count) {
- observer_->OnCandidateWindowCountChanged(window_count);
-}
-
-void TSFEventRouter::OnTSFStartComposition() {
- observer_->OnTSFStartComposition();
-}
-
-void TSFEventRouter::OnTextUpdated(const gfx::Range& composition_range) {
- observer_->OnTextUpdated(composition_range);
-}
-
-void TSFEventRouter::OnTSFEndComposition() {
- observer_->OnTSFEndComposition();
-}
-
-void TSFEventRouter::SetManager(ITfThreadMgr* thread_manager) {
- delegate_->SetManager(thread_manager);
-}
-
-} // namespace ui
diff --git a/chromium/ui/base/ime/win/tsf_event_router.h b/chromium/ui/base/ime/win/tsf_event_router.h
deleted file mode 100644
index 04a2a1e9eb0..00000000000
--- a/chromium/ui/base/ime/win/tsf_event_router.h
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright (c) 2012 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.
-
-#ifndef UI_BASE_IME_WIN_TSF_EVENT_ROUTER_H_
-#define UI_BASE_IME_WIN_TSF_EVENT_ROUTER_H_
-
-#include <atlbase.h>
-#include <atlcom.h>
-#include <msctf.h>
-
-#include <set>
-
-#include "base/basictypes.h"
-#include "base/callback.h"
-#include "base/compiler_specific.h"
-#include "ui/base/ime/text_input_type.h"
-#include "ui/base/ui_export.h"
-#include "ui/gfx/range/range.h"
-
-struct ITfDocumentMgr;
-
-namespace ui {
-
-class TSFEventRouterObserver {
- public:
- TSFEventRouterObserver() {}
-
- // Called when the number of currently opened candidate windows changes.
- virtual void OnCandidateWindowCountChanged(size_t window_count) {}
-
- // Called when a composition is started.
- virtual void OnTSFStartComposition() {}
-
- // Called when the text contents are updated. If there is no composition,
- // gfx::Range::InvalidRange is passed to |composition_range|.
- virtual void OnTextUpdated(const gfx::Range& composition_range) {}
-
- // Called when a composition is terminated.
- virtual void OnTSFEndComposition() {}
-
- protected:
- virtual ~TSFEventRouterObserver() {}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TSFEventRouterObserver);
-};
-
-// This class monitores TSF related events and forwards them to given
-// |observer|.
-class UI_EXPORT TSFEventRouter {
- public:
- // Do not pass NULL to |observer|.
- explicit TSFEventRouter(TSFEventRouterObserver* observer);
- virtual ~TSFEventRouter();
-
- // Returns true if the IME is composing text.
- bool IsImeComposing();
-
- // Callbacks from the TSFEventRouterDelegate:
- void OnCandidateWindowCountChanged(size_t window_count);
- void OnTSFStartComposition();
- void OnTextUpdated(const gfx::Range& composition_range);
- void OnTSFEndComposition();
-
- // Sets |thread_manager| to be monitored. |thread_manager| can be NULL.
- void SetManager(ITfThreadMgr* thread_manager);
-
- private:
- class Delegate;
-
- CComPtr<Delegate> delegate_;
-
- TSFEventRouterObserver* observer_;
-
- DISALLOW_COPY_AND_ASSIGN(TSFEventRouter);
-};
-
-} // namespace ui
-
-#endif // UI_BASE_IME_WIN_TSF_EVENT_ROUTER_H_
diff --git a/chromium/ui/base/ime/win/tsf_input_scope.cc b/chromium/ui/base/ime/win/tsf_input_scope.cc
index 06481e9d8f0..f40f928a5f7 100644
--- a/chromium/ui/base/ime/win/tsf_input_scope.cc
+++ b/chromium/ui/base/ime/win/tsf_input_scope.cc
@@ -29,7 +29,7 @@ void AppendNonTrivialInputScope(std::vector<InputScope>* input_scopes,
input_scopes->push_back(input_scope);
}
-class TSFInputScope : public ITfInputScope {
+class TSFInputScope FINAL : public ITfInputScope {
public:
explicit TSFInputScope(const std::vector<InputScope>& input_scopes)
: input_scopes_(input_scopes),
@@ -116,7 +116,7 @@ SetInputScopesFunc g_set_input_scopes = NULL;
bool g_get_proc_done = false;
SetInputScopesFunc GetSetInputScopes() {
- DCHECK_EQ(base::MessageLoop::TYPE_UI, base::MessageLoop::current()->type());
+ DCHECK(base::MessageLoopForUI::IsCurrent());
// Thread safety is not required because this function is under UI thread.
if (!g_get_proc_done) {
g_get_proc_done = true;
diff --git a/chromium/ui/base/ime/win/tsf_input_scope.h b/chromium/ui/base/ime/win/tsf_input_scope.h
index 2e5856c60d8..536d395dce1 100644
--- a/chromium/ui/base/ime/win/tsf_input_scope.h
+++ b/chromium/ui/base/ime/win/tsf_input_scope.h
@@ -12,7 +12,7 @@
#include "base/basictypes.h"
#include "ui/base/ime/text_input_mode.h"
#include "ui/base/ime/text_input_type.h"
-#include "ui/base/ui_export.h"
+#include "ui/base/ui_base_export.h"
namespace ui {
namespace tsf_inputscope {
@@ -20,8 +20,9 @@ namespace tsf_inputscope {
// Returns InputScope list corresoponding to ui::TextInputType and
// ui::TextInputMode.
// This function is only used from following functions but declared for test.
-UI_EXPORT std::vector<InputScope> GetInputScopes(TextInputType text_input_type,
- TextInputMode text_input_mode);
+UI_BASE_EXPORT std::vector<InputScope> GetInputScopes(
+ TextInputType text_input_type,
+ TextInputMode text_input_mode);
// Returns an instance of ITfInputScope, which is the Windows-specific
// category representation corresponding to ui::TextInputType and
@@ -29,14 +30,14 @@ UI_EXPORT std::vector<InputScope> GetInputScopes(TextInputType text_input_type,
// in the target field.
// The returned instance has 0 reference count. The caller must maintain its
// reference count.
-UI_EXPORT ITfInputScope* CreateInputScope(TextInputType text_input_type,
- TextInputMode text_input_mode);
+UI_BASE_EXPORT ITfInputScope* CreateInputScope(TextInputType text_input_type,
+ TextInputMode text_input_mode);
// A wrapper of the SetInputScopes API exported by msctf.dll.
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms629026.aspx
// Does nothing on Windows XP in case TSF is disabled.
// NOTE: For TSF-aware window, you should use ITfInputScope instead.
-UI_EXPORT void SetInputScopeForTsfUnawareWindow(
+UI_BASE_EXPORT void SetInputScopeForTsfUnawareWindow(
HWND window_handle,
TextInputType text_input_type,
TextInputMode text_input_mode);
diff --git a/chromium/ui/base/ime/win/tsf_text_store.cc b/chromium/ui/base/ime/win/tsf_text_store.cc
deleted file mode 100644
index 0ef34b5be89..00000000000
--- a/chromium/ui/base/ime/win/tsf_text_store.cc
+++ /dev/null
@@ -1,923 +0,0 @@
-// Copyright (c) 2012 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 <InputScope.h>
-#include <OleCtl.h>
-
-#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"
-
-namespace ui {
-namespace {
-
-// We support only one view.
-const TsViewCookie kViewCookie = 1;
-
-} // namespace
-
-TSFTextStore::TSFTextStore()
- : ref_count_(0),
- text_store_acp_sink_mask_(0),
- window_handle_(NULL),
- text_input_client_(NULL),
- committed_size_(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;
- }
-}
-
-TSFTextStore::~TSFTextStore() {
-}
-
-ULONG STDMETHODCALLTYPE TSFTextStore::AddRef() {
- return InterlockedIncrement(&ref_count_);
-}
-
-ULONG STDMETHODCALLTYPE TSFTextStore::Release() {
- const LONG count = InterlockedDecrement(&ref_count_);
- if (!count) {
- delete this;
- return 0;
- }
- return static_cast<ULONG>(count);
-}
-
-STDMETHODIMP TSFTextStore::QueryInterface(REFIID iid, void** result) {
- if (iid == IID_IUnknown || iid == IID_ITextStoreACP) {
- *result = static_cast<ITextStoreACP*>(this);
- } else if (iid == IID_ITfContextOwnerCompositionSink) {
- *result = static_cast<ITfContextOwnerCompositionSink*>(this);
- } else if (iid == IID_ITfTextEditSink) {
- *result = static_cast<ITfTextEditSink*>(this);
- } else {
- *result = NULL;
- return E_NOINTERFACE;
- }
- AddRef();
- return S_OK;
-}
-
-STDMETHODIMP TSFTextStore::AdviseSink(REFIID iid,
- IUnknown* unknown,
- DWORD mask) {
- if (!IsEqualGUID(iid, IID_ITextStoreACPSink))
- return E_INVALIDARG;
- if (text_store_acp_sink_) {
- if (text_store_acp_sink_.IsSameObject(unknown)) {
- text_store_acp_sink_mask_ = mask;
- return S_OK;
- } else {
- return CONNECT_E_ADVISELIMIT;
- }
- }
- if (FAILED(text_store_acp_sink_.QueryFrom(unknown)))
- return E_UNEXPECTED;
- text_store_acp_sink_mask_ = mask;
-
- return S_OK;
-}
-
-STDMETHODIMP TSFTextStore::FindNextAttrTransition(
- LONG acp_start,
- LONG acp_halt,
- ULONG num_filter_attributes,
- const TS_ATTRID* filter_attributes,
- DWORD flags,
- LONG* acp_next,
- BOOL* found,
- LONG* found_offset) {
- if (!acp_next || !found || !found_offset)
- return E_INVALIDARG;
- // We don't support any attributes.
- // So we always return "not found".
- *acp_next = 0;
- *found = FALSE;
- *found_offset = 0;
- return S_OK;
-}
-
-STDMETHODIMP TSFTextStore::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) {
- if (!view_cookie)
- return E_INVALIDARG;
- // We support only one view.
- *view_cookie = kViewCookie;
- return S_OK;
-}
-
-STDMETHODIMP TSFTextStore::GetEmbedded(LONG acp_pos,
- REFGUID service,
- REFIID iid,
- IUnknown** unknown) {
- // We don't support any embedded objects.
- NOTIMPLEMENTED();
- if (!unknown)
- return E_INVALIDARG;
- *unknown = NULL;
- return E_NOTIMPL;
-}
-
-STDMETHODIMP TSFTextStore::GetEndACP(LONG* acp) {
- if (!acp)
- return E_INVALIDARG;
- if (!HasReadLock())
- return TS_E_NOLOCK;
- *acp = string_buffer_.size();
- return S_OK;
-}
-
-STDMETHODIMP TSFTextStore::GetFormattedText(LONG acp_start, LONG acp_end,
- IDataObject** data_object) {
- NOTIMPLEMENTED();
- return E_NOTIMPL;
-}
-
-STDMETHODIMP TSFTextStore::GetScreenExt(TsViewCookie view_cookie, RECT* rect) {
- if (view_cookie != kViewCookie)
- return E_INVALIDARG;
- if (!rect)
- return E_INVALIDARG;
-
- // {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;
- POINT left_top = {client_rect.left, client_rect.top};
- POINT right_bottom = {client_rect.right, client_rect.bottom};
- if (!ClientToScreen(window_handle_, &left_top))
- return E_FAIL;
- if (!ClientToScreen(window_handle_, &right_bottom))
- return E_FAIL;
-
- rect->left = left_top.x;
- rect->top = left_top.y;
- rect->right = right_bottom.x;
- rect->bottom = right_bottom.y;
- return S_OK;
-}
-
-STDMETHODIMP TSFTextStore::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)
- return E_INVALIDARG;
- if (!HasReadLock())
- return TS_E_NOLOCK;
- *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].style.ase = TS_AE_END;
- selection_buffer[0].style.fInterimChar = FALSE;
- *fetched_count = 1;
- }
- return S_OK;
-}
-
-STDMETHODIMP TSFTextStore::GetStatus(TS_STATUS* status) {
- if (!status)
- return E_INVALIDARG;
-
- status->dwDynamicFlags = 0;
- // We use transitory contexts and we don't support hidden text.
- status->dwStaticFlags = TS_SS_TRANSITORY | TS_SS_NOHIDDENTEXT;
-
- 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) {
- if (!text_buffer_copied || !run_info_buffer_copied)
- return E_INVALIDARG;
- if (!text_buffer && text_buffer_size != 0)
- return E_INVALIDARG;
- if (!run_info_buffer && run_info_buffer_size != 0)
- return E_INVALIDARG;
- if (!next_acp)
- return E_INVALIDARG;
- if (!HasReadLock())
- return TF_E_NOLOCK;
- const LONG string_buffer_size = string_buffer_.size();
- if (acp_end == -1)
- acp_end = string_buffer_size;
- if (!((0 <= acp_start) &&
- (acp_start <= acp_end) &&
- (acp_end <= string_buffer_size))) {
- return TF_E_INVALIDPOS;
- }
- acp_end = std::min(acp_end, acp_start + static_cast<LONG>(text_buffer_size));
- *text_buffer_copied = acp_end - acp_start;
-
- const string16& result =
- string_buffer_.substr(acp_start, *text_buffer_copied);
- for (size_t i = 0; i < result.size(); ++i) {
- text_buffer[i] = result[i];
- }
-
- if (run_info_buffer_size) {
- run_info_buffer[0].uCount = *text_buffer_copied;
- run_info_buffer[0].type = TS_RT_PLAIN;
- *run_info_buffer_copied = 1;
- }
-
- *next_acp = acp_end;
- return S_OK;
-}
-
-STDMETHODIMP TSFTextStore::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())
- return TS_E_NOLOCK;
- if (!((static_cast<LONG>(committed_size_) <= acp_start) &&
- (acp_start <= acp_end) &&
- (acp_end <= static_cast<LONG>(string_buffer_.size())))) {
- return TS_E_INVALIDPOS;
- }
-
- // According to a behavior of notepad.exe and wordpad.exe, top left corner of
- // rect indicates a first character's one, and bottom right corner of rect
- // 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;
- const uint32 start_pos = acp_start - committed_size_;
- const uint32 end_pos = acp_end - committed_size_;
-
- if (start_pos == end_pos) {
- // According to MSDN document, if |acp_start| and |acp_end| are equal it is
- // OK to just return E_INVALIDARG.
- // http://msdn.microsoft.com/en-us/library/ms538435
- // 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();
- } else if (string_buffer_.size() == committed_size_) {
- result = text_input_client_->GetCaretBounds().ToRECT();
- } 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 {
- 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();
- } 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.
- }
- } else {
- // Hack for PPAPI flash. PPAPI flash does not support GetCaretBounds, so
- // 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();
- } else {
- return TS_E_NOLAYOUT;
- }
- }
- }
-
- *rect = result;
- *clipped = FALSE;
- return S_OK;
-}
-
-STDMETHODIMP TSFTextStore::GetWnd(TsViewCookie view_cookie,
- HWND* window_handle) {
- if (!window_handle)
- return E_INVALIDARG;
- if (view_cookie != kViewCookie)
- return E_INVALIDARG;
- *window_handle = window_handle_;
- return S_OK;
-}
-
-STDMETHODIMP TSFTextStore::InsertEmbedded(DWORD flags,
- LONG acp_start,
- LONG acp_end,
- IDataObject* data_object,
- TS_TEXTCHANGE* change) {
- // We don't support any embedded objects.
- NOTIMPLEMENTED();
- return E_NOTIMPL;
-}
-
-STDMETHODIMP TSFTextStore::InsertEmbeddedAtSelection(DWORD flags,
- IDataObject* data_object,
- LONG* acp_start,
- LONG* acp_end,
- TS_TEXTCHANGE* change) {
- // We don't support any embedded objects.
- NOTIMPLEMENTED();
- return E_NOTIMPL;
-}
-
-STDMETHODIMP TSFTextStore::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 new_end_pos = start_pos + text_buffer_size;
-
- if (flags & TS_IAS_QUERYONLY) {
- if (!HasReadLock())
- return TS_E_NOLOCK;
- if (acp_start)
- *acp_start = start_pos;
- if (acp_end) {
- *acp_end = end_pos;
- }
- return S_OK;
- }
-
- if (!HasReadWriteLock())
- return TS_E_NOLOCK;
- if (!text_buffer)
- return E_INVALIDARG;
-
- DCHECK_LE(start_pos, end_pos);
- string_buffer_ = string_buffer_.substr(0, start_pos) +
- string16(text_buffer, text_buffer + text_buffer_size) +
- string_buffer_.substr(end_pos);
- if (acp_start)
- *acp_start = start_pos;
- if (acp_end)
- *acp_end = new_end_pos;
- if (text_change) {
- text_change->acpStart = start_pos;
- text_change->acpOldEnd = end_pos;
- text_change->acpNewEnd = new_end_pos;
- }
- selection_.set_start(start_pos);
- selection_.set_end(new_end_pos);
- return S_OK;
-}
-
-STDMETHODIMP TSFTextStore::QueryInsert(
- LONG acp_test_start,
- LONG acp_test_end,
- ULONG text_size,
- LONG* acp_result_start,
- LONG* acp_result_end) {
- if (!acp_result_start || !acp_result_end || acp_test_start > acp_test_end)
- return E_INVALIDARG;
- const LONG committed_size = static_cast<LONG>(committed_size_);
- const LONG buffer_size = static_cast<LONG>(string_buffer_.size());
- *acp_result_start = std::min(std::max(committed_size, acp_test_start),
- buffer_size);
- *acp_result_end = std::min(std::max(committed_size, acp_test_end),
- buffer_size);
- return S_OK;
-}
-
-STDMETHODIMP TSFTextStore::QueryInsertEmbedded(const GUID* service,
- const FORMATETC* format,
- BOOL* insertable) {
- if (!format)
- return E_INVALIDARG;
- // We don't support any embedded objects.
- if (insertable)
- *insertable = FALSE;
- return S_OK;
-}
-
-STDMETHODIMP TSFTextStore::RequestAttrsAtPosition(
- LONG acp_pos,
- ULONG attribute_buffer_size,
- const TS_ATTRID* attribute_buffer,
- DWORD flags) {
- // We don't support any document attributes.
- // This method just returns S_OK, and the subsequently called
- // RetrieveRequestedAttrs() returns 0 as the number of supported attributes.
- return S_OK;
-}
-
-STDMETHODIMP TSFTextStore::RequestAttrsTransitioningAtPosition(
- LONG acp_pos,
- ULONG attribute_buffer_size,
- const TS_ATTRID* attribute_buffer,
- DWORD flags) {
- // We don't support any document attributes.
- // This method just returns S_OK, and the subsequently called
- // RetrieveRequestedAttrs() returns 0 as the number of supported attributes.
- return S_OK;
-}
-
-STDMETHODIMP TSFTextStore::RequestLock(DWORD lock_flags, HRESULT* result) {
- if (!text_store_acp_sink_.get())
- return E_FAIL;
- if (!result)
- return E_INVALIDARG;
-
- if (current_lock_type_ != 0) {
- if (lock_flags & TS_LF_SYNC) {
- // Can't lock synchronously.
- *result = TS_E_SYNCHRONOUS;
- return S_OK;
- }
- // Queue the lock request.
- lock_queue_.push_back(lock_flags & TS_LF_READWRITE);
- *result = TS_S_ASYNC;
- return S_OK;
- }
-
- // Lock
- current_lock_type_ = (lock_flags & TS_LF_READWRITE);
-
- edit_flag_ = false;
- const size_t last_committed_size = committed_size_;
-
- // Grant the lock.
- *result = text_store_acp_sink_->OnLockGranted(current_lock_type_);
-
- // Unlock
- current_lock_type_ = 0;
-
- // Handles the pending lock requests.
- while (!lock_queue_.empty()) {
- current_lock_type_ = lock_queue_.front();
- lock_queue_.pop_front();
- text_store_acp_sink_->OnLockGranted(current_lock_type_);
- current_lock_type_ = 0;
- }
-
- if (!edit_flag_) {
- return S_OK;
- }
-
- // If the text store is edited in OnLockGranted(), we may need to call
- // TextInputClient::InsertText() or TextInputClient::SetCompositionText().
- const size_t new_committed_size = committed_size_;
- const string16& new_committed_string =
- string_buffer_.substr(last_committed_size,
- new_committed_size - last_committed_size);
- 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 (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);
- 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;
- textChange.acpStart = 0;
- textChange.acpOldEnd = new_committed_size;
- textChange.acpNewEnd = 0;
- text_store_acp_sink_->OnTextChange(0, &textChange);
- }
- }
-
- return S_OK;
-}
-
-STDMETHODIMP TSFTextStore::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_)
- return E_FAIL;
- // We support only input scope attribute.
- for (size_t i = 0; i < attribute_buffer_size; ++i) {
- if (IsEqualGUID(GUID_PROP_INPUTSCOPE, attribute_buffer[i]))
- return S_OK;
- }
- return E_FAIL;
-}
-
-STDMETHODIMP TSFTextStore::RetrieveRequestedAttrs(
- ULONG attribute_buffer_size,
- TS_ATTRVAL* attribute_buffer,
- ULONG* attribute_buffer_copied) {
- if (!attribute_buffer_copied)
- return E_INVALIDARG;
- if (!attribute_buffer)
- return E_INVALIDARG;
- if (!text_input_client_)
- return E_UNEXPECTED;
- // 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->AddRef();
- *attribute_buffer_copied = 1;
- return S_OK;
-}
-
-STDMETHODIMP TSFTextStore::SetSelection(
- ULONG selection_buffer_size,
- const TS_SELECTION_ACP* selection_buffer) {
- if (!HasReadWriteLock())
- return TF_E_NOLOCK;
- if (selection_buffer_size > 0) {
- const LONG start_pos = selection_buffer[0].acpStart;
- const LONG end_pos = selection_buffer[0].acpEnd;
- if (!((static_cast<LONG>(committed_size_) <= start_pos) &&
- (start_pos <= end_pos) &&
- (end_pos <= static_cast<LONG>(string_buffer_.size())))) {
- return TF_E_INVALIDPOS;
- }
- selection_.set_start(start_pos);
- selection_.set_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) {
- if (!HasReadWriteLock())
- return TS_E_NOLOCK;
- if (!((static_cast<LONG>(committed_size_) <= acp_start) &&
- (acp_start <= acp_end) &&
- (acp_end <= static_cast<LONG>(string_buffer_.size())))) {
- return TS_E_INVALIDPOS;
- }
-
- 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);
- if (ret != S_OK)
- return ret;
-
- TS_TEXTCHANGE change;
- ret = InsertTextAtSelection(0, text_buffer, text_buffer_size,
- &acp_start, &acp_end, &change);
- if (ret != S_OK)
- return ret;
-
- if (text_change)
- *text_change = change;
-
- return S_OK;
-}
-
-STDMETHODIMP TSFTextStore::UnadviseSink(IUnknown* unknown) {
- if (!text_store_acp_sink_.IsSameObject(unknown))
- return CONNECT_E_NOCONNECTION;
- text_store_acp_sink_.Release();
- text_store_acp_sink_mask_ = 0;
- return S_OK;
-}
-
-STDMETHODIMP TSFTextStore::OnStartComposition(
- ITfCompositionView* composition_view,
- BOOL* ok) {
- if (ok)
- *ok = TRUE;
- return S_OK;
-}
-
-STDMETHODIMP TSFTextStore::OnUpdateComposition(
- ITfCompositionView* composition_view,
- ITfRange* range) {
- return S_OK;
-}
-
-STDMETHODIMP TSFTextStore::OnEndComposition(
- ITfCompositionView* composition_view) {
- return S_OK;
-}
-
-STDMETHODIMP TSFTextStore::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)) {
- 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) {
- GUID guid;
- if (FAILED(category_manager_->GetGUID(guid_atom, &guid)))
- return false;
-
- base::win::ScopedComPtr<ITfDisplayAttributeInfo> display_attribute_info;
- if (FAILED(display_attribute_manager_->GetDisplayAttributeInfo(
- guid, display_attribute_info.Receive(), NULL))) {
- return false;
- }
- return SUCCEEDED(display_attribute_info->GetAttributeInfo(attribute));
-}
-
-bool TSFTextStore::GetCompositionStatus(
- ITfContext* context,
- const TfEditCookie read_only_edit_cookie,
- size_t* committed_size,
- CompositionUnderlines* undelines) {
- DCHECK(context);
- DCHECK(committed_size);
- DCHECK(undelines);
- const GUID* rgGuids[2] = {&GUID_PROP_COMPOSING, &GUID_PROP_ATTRIBUTE};
- base::win::ScopedComPtr<ITfReadOnlyProperty> track_property;
- if (FAILED(context->TrackProperties(rgGuids, 2, NULL, 0,
- track_property.Receive()))) {
- return false;
- }
-
- *committed_size = 0;
- undelines->clear();
- base::win::ScopedComPtr<ITfRange> start_to_end_range;
- base::win::ScopedComPtr<ITfRange> end_range;
- if (FAILED(context->GetStart(read_only_edit_cookie,
- start_to_end_range.Receive()))) {
- return false;
- }
- if (FAILED(context->GetEnd(read_only_edit_cookie, end_range.Receive())))
- return false;
- if (FAILED(start_to_end_range->ShiftEndToRange(read_only_edit_cookie,
- end_range, TF_ANCHOR_END))) {
- return false;
- }
-
- base::win::ScopedComPtr<IEnumTfRanges> ranges;
- if (FAILED(track_property->EnumRanges(read_only_edit_cookie, ranges.Receive(),
- start_to_end_range))) {
- return false;
- }
-
- while (true) {
- base::win::ScopedComPtr<ITfRange> range;
- if (ranges->Next(1, range.Receive(), NULL) != S_OK)
- break;
- base::win::ScopedVariant value;
- base::win::ScopedComPtr<IEnumTfPropertyValue> enum_prop_value;
- if (FAILED(track_property->GetValue(read_only_edit_cookie, range,
- value.Receive()))) {
- return false;
- }
- if (FAILED(enum_prop_value.QueryFrom(value.AsInput()->punkVal)))
- return false;
-
- TF_PROPERTYVAL property_value;
- bool is_composition = false;
- bool has_display_attribute = false;
- TF_DISPLAYATTRIBUTE display_attribute;
- while (enum_prop_value->Next(1, &property_value, NULL) == S_OK) {
- if (IsEqualGUID(property_value.guidId, GUID_PROP_COMPOSING)) {
- is_composition = (property_value.varValue.lVal == TRUE);
- } else if (IsEqualGUID(property_value.guidId, GUID_PROP_ATTRIBUTE)) {
- TfGuidAtom guid_atom =
- static_cast<TfGuidAtom>(property_value.varValue.lVal);
- if (GetDisplayAttribute(guid_atom, &display_attribute))
- has_display_attribute = true;
- }
- VariantClear(&property_value.varValue);
- }
-
- base::win::ScopedComPtr<ITfRangeACP> range_acp;
- range_acp.QueryFrom(range);
- LONG start_pos, length;
- range_acp->GetExtent(&start_pos, &length);
- if (!is_composition) {
- if (*committed_size < static_cast<size_t>(start_pos + length))
- *committed_size = start_pos + length;
- } else {
- CompositionUnderline 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;
- 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_)
- return false;
-
- if (string_buffer_.empty())
- return true;
-
- // Unlike ImmNotifyIME(NI_COMPOSITIONSTR, CPS_CANCEL, 0) in IMM32, TSF does
- // not have a dedicated method to cancel composition. However, CUAS actually
- // has a protocol conversion from CPS_CANCEL into TSF operations. According
- // to the observations on Windows 7, TIPs are expected to cancel composition
- // when an on-going composition text is replaced with an empty string. So
- // we use the same operation to cancel composition here to minimize the risk
- // of potential compatibility issues.
-
- const size_t previous_buffer_size = string_buffer_.size();
- string_buffer_.clear();
- committed_size_ = 0;
- selection_.set_start(0);
- selection_.set_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 = {};
- textChange.acpStart = 0;
- textChange.acpOldEnd = previous_buffer_size;
- textChange.acpNewEnd = 0;
- text_store_acp_sink_->OnTextChange(0, &textChange);
- }
- return true;
-}
-
-bool TSFTextStore::ConfirmComposition() {
- // If there is an on-going document lock, we must not edit the text.
- if (edit_flag_)
- return false;
-
- if (string_buffer_.empty())
- return true;
-
- // See the comment in TSFTextStore::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);
-
- const size_t previous_buffer_size = string_buffer_.size();
- string_buffer_.clear();
- committed_size_ = 0;
- selection_.set_start(0);
- selection_.set_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 = {};
- textChange.acpStart = 0;
- textChange.acpOldEnd = previous_buffer_size;
- textChange.acpNewEnd = 0;
- text_store_acp_sink_->OnTextChange(0, &textChange);
- }
- return true;
-}
-
-void TSFTextStore::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 {
- return (current_lock_type_ & TS_LF_READ) == TS_LF_READ;
-}
-
-bool TSFTextStore::HasReadWriteLock() const {
- return (current_lock_type_ & TS_LF_READWRITE) == TS_LF_READWRITE;
-}
-
-} // namespace ui
diff --git a/chromium/ui/base/ime/win/tsf_text_store.h b/chromium/ui/base/ime/win/tsf_text_store.h
deleted file mode 100644
index 87cd6b42991..00000000000
--- a/chromium/ui/base/ime/win/tsf_text_store.h
+++ /dev/null
@@ -1,297 +0,0 @@
-// Copyright (c) 2012 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.
-
-#ifndef UI_BASE_IME_WIN_TSF_TEXT_STORE_H_
-#define UI_BASE_IME_WIN_TSF_TEXT_STORE_H_
-
-#include <msctf.h>
-#include <deque>
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "base/strings/string16.h"
-#include "base/win/scoped_comptr.h"
-#include "ui/base/ime/composition_underline.h"
-#include "ui/base/ui_export.h"
-#include "ui/gfx/range/range.h"
-
-namespace ui {
-class TextInputClient;
-
-// TSFTextStore is used to interact with the input method via TSF manager.
-// TSFTextStore have a string buffer which is manipulated by TSF manager through
-// ITextStoreACP interface methods such as SetText().
-// When the input method updates the composition, TSFTextStore calls
-// TextInputClient::SetCompositionText(). And when the input method finishes the
-// composition, TSFTextStore calls TextInputClient::InsertText() and clears the
-// buffer.
-//
-// How TSFTextStore works:
-// - The user enters "a".
-// - The input method set composition as "a".
-// - TSF manager calls TSFTextStore::RequestLock().
-// - TSFTextStore callbacks ITextStoreACPSink::OnLockGranted().
-// - In OnLockGranted(), TSF manager calls
-// - TSFTextStore::OnStartComposition()
-// - TSFTextStore::SetText()
-// The string buffer is set as "a".
-// - TSFTextStore::OnUpdateComposition()
-// - TSFTextStore::OnEndEdit()
-// TSFTextStore can get the composition information such as underlines.
-// - TSFTextStore calls TextInputClient::SetCompositionText().
-// "a" is shown with an underline as composition string.
-// - The user enters <space>.
-// - The input method set composition as "A".
-// - TSF manager calls TSFTextStore::RequestLock().
-// - TSFTextStore callbacks ITextStoreACPSink::OnLockGranted().
-// - In OnLockGranted(), TSF manager calls
-// - TSFTextStore::SetText()
-// The string buffer is set as "A".
-// - TSFTextStore::OnUpdateComposition()
-// - TSFTextStore::OnEndEdit()
-// - TSFTextStore calls TextInputClient::SetCompositionText().
-// "A" is shown with an underline as composition string.
-// - The user enters <enter>.
-// - The input method commits "A".
-// - TSF manager calls TSFTextStore::RequestLock().
-// - TSFTextStore callbacks ITextStoreACPSink::OnLockGranted().
-// - In OnLockGranted(), TSF manager calls
-// - TSFTextStore::OnEndComposition()
-// - TSFTextStore::OnEndEdit()
-// TSFTextStore knows "A" is committed.
-// - TSFTextStore calls TextInputClient::InsertText().
-// "A" is shown as committed string.
-// - TSFTextStore clears the string buffer.
-// - TSFTextStore calls OnSelectionChange(), OnLayoutChange() and
-// OnTextChange() of ITextStoreACPSink to let TSF manager know that the
-// string buffer has been changed.
-//
-// About the locking scheme:
-// When TSF manager manipulates the string buffer it calls RequestLock() to get
-// the lock of the document. If TSFTextStore can grant the lock request, it
-// callbacks ITextStoreACPSink::OnLockGranted().
-// RequestLock() is called from only one thread, but called recursively in
-// OnLockGranted() or OnSelectionChange() or OnLayoutChange() or OnTextChange().
-// If the document is locked and the lock request is asynchronous, TSFTextStore
-// queues the request. The queued requests will be handled after the current
-// lock is removed.
-// More information about document locks can be found here:
-// http://msdn.microsoft.com/en-us/library/ms538064
-//
-// More information about TSF can be found here:
-// http://msdn.microsoft.com/en-us/library/ms629032
-class UI_EXPORT TSFTextStore : public ITextStoreACP,
- public ITfContextOwnerCompositionSink,
- public ITfTextEditSink {
- public:
- TSFTextStore();
- virtual ~TSFTextStore();
-
- // ITextStoreACP:
- STDMETHOD_(ULONG, AddRef)() OVERRIDE;
- STDMETHOD_(ULONG, Release)() OVERRIDE;
- STDMETHOD(QueryInterface)(REFIID iid, void** ppv) OVERRIDE;
- STDMETHOD(AdviseSink)(REFIID iid, IUnknown* unknown, DWORD mask) OVERRIDE;
- STDMETHOD(FindNextAttrTransition)(LONG acp_start,
- LONG acp_halt,
- ULONG num_filter_attributes,
- const TS_ATTRID* filter_attributes,
- DWORD flags,
- LONG* acp_next,
- BOOL* found,
- LONG* found_offset) OVERRIDE;
- STDMETHOD(GetACPFromPoint)(TsViewCookie view_cookie,
- const POINT* point,
- DWORD flags,
- LONG* acp) OVERRIDE;
- STDMETHOD(GetActiveView)(TsViewCookie* view_cookie) OVERRIDE;
- STDMETHOD(GetEmbedded)(LONG acp_pos,
- REFGUID service,
- REFIID iid,
- IUnknown** unknown) OVERRIDE;
- STDMETHOD(GetEndACP)(LONG* acp) OVERRIDE;
- STDMETHOD(GetFormattedText)(LONG acp_start,
- LONG acp_end,
- IDataObject** data_object) OVERRIDE;
- STDMETHOD(GetScreenExt)(TsViewCookie view_cookie, RECT* rect) OVERRIDE;
- STDMETHOD(GetSelection)(ULONG selection_index,
- ULONG selection_buffer_size,
- TS_SELECTION_ACP* selection_buffer,
- ULONG* fetched_count) OVERRIDE;
- STDMETHOD(GetStatus)(TS_STATUS* pdcs) OVERRIDE;
- STDMETHOD(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) OVERRIDE;
- STDMETHOD(GetTextExt)(TsViewCookie view_cookie,
- LONG acp_start,
- LONG acp_end,
- RECT* rect,
- BOOL* clipped) OVERRIDE;
- STDMETHOD(GetWnd)(TsViewCookie view_cookie, HWND* window_handle) OVERRIDE;
- STDMETHOD(InsertEmbedded)(DWORD flags,
- LONG acp_start,
- LONG acp_end,
- IDataObject* data_object,
- TS_TEXTCHANGE* change) OVERRIDE;
- STDMETHOD(InsertEmbeddedAtSelection)(DWORD flags,
- IDataObject* data_object,
- LONG* acp_start,
- LONG* acp_end,
- TS_TEXTCHANGE* change) OVERRIDE;
- STDMETHOD(InsertTextAtSelection)(DWORD flags,
- const wchar_t* text_buffer,
- ULONG text_buffer_size,
- LONG* acp_start,
- LONG* acp_end,
- TS_TEXTCHANGE* text_change) OVERRIDE;
- STDMETHOD(QueryInsert)(LONG acp_test_start,
- LONG acp_test_end,
- ULONG text_size,
- LONG* acp_result_start,
- LONG* acp_result_end) OVERRIDE;
- STDMETHOD(QueryInsertEmbedded)(const GUID* service,
- const FORMATETC* format,
- BOOL* insertable) OVERRIDE;
- STDMETHOD(RequestAttrsAtPosition)(LONG acp_pos,
- ULONG attribute_buffer_size,
- const TS_ATTRID* attribute_buffer,
- DWORD flags) OVERRIDE;
- STDMETHOD(RequestAttrsTransitioningAtPosition)(
- LONG acp_pos,
- ULONG attribute_buffer_size,
- const TS_ATTRID* attribute_buffer,
- DWORD flags) OVERRIDE;
- STDMETHOD(RequestLock)(DWORD lock_flags, HRESULT* result) OVERRIDE;
- STDMETHOD(RequestSupportedAttrs)(DWORD flags,
- ULONG attribute_buffer_size,
- const TS_ATTRID* attribute_buffer) OVERRIDE;
- STDMETHOD(RetrieveRequestedAttrs)(ULONG attribute_buffer_size,
- TS_ATTRVAL* attribute_buffer,
- ULONG* attribute_buffer_copied) OVERRIDE;
- STDMETHOD(SetSelection)(ULONG selection_buffer_size,
- const TS_SELECTION_ACP* selection_buffer) OVERRIDE;
- STDMETHOD(SetText)(DWORD flags,
- LONG acp_start,
- LONG acp_end,
- const wchar_t* text_buffer,
- ULONG text_buffer_size,
- TS_TEXTCHANGE* text_change) OVERRIDE;
- STDMETHOD(UnadviseSink)(IUnknown* unknown) OVERRIDE;
-
- // ITfContextOwnerCompositionSink:
- STDMETHOD(OnStartComposition)(ITfCompositionView* composition_view,
- BOOL* ok) OVERRIDE;
- STDMETHOD(OnUpdateComposition)(ITfCompositionView* composition_view,
- ITfRange* range) OVERRIDE;
- STDMETHOD(OnEndComposition)(ITfCompositionView* composition_view) OVERRIDE;
-
- // ITfTextEditSink:
- STDMETHOD(OnEndEdit)(ITfContext* context, TfEditCookie read_only_edit_cookie,
- ITfEditRecord* edit_record) OVERRIDE;
-
- // Sets currently focused TextInputClient.
- void SetFocusedTextInputClient(HWND focused_window,
- TextInputClient* text_input_client);
- // Removes currently focused TextInputClient.
- void RemoveFocusedTextInputClient(TextInputClient* text_input_client);
-
- // Cancels the ongoing composition if exists.
- bool CancelComposition();
-
- // Confirms the ongoing composition if exists.
- bool ConfirmComposition();
-
- // Sends OnLayoutChange() via |text_store_acp_sink_|.
- void SendOnLayoutChange();
-
- private:
- friend class TSFTextStoreTest;
- friend class TSFTextStoreTestCallback;
-
- // Checks if the document has a read-only lock.
- bool HasReadLock() const;
-
- // Checks if the document has a read and write lock.
- bool HasReadWriteLock() const;
-
- // Gets the display attribute structure.
- bool GetDisplayAttribute(TfGuidAtom guid_atom,
- TF_DISPLAYATTRIBUTE* attribute);
-
- // Gets the committed string size and underline information of the context.
- bool GetCompositionStatus(ITfContext* context,
- const TfEditCookie read_only_edit_cookie,
- size_t* committed_size,
- CompositionUnderlines* undelines);
-
- // The refrence count of this instance.
- volatile LONG ref_count_;
-
- // A pointer of ITextStoreACPSink, this instance is given in AdviseSink.
- base::win::ScopedComPtr<ITextStoreACPSink> text_store_acp_sink_;
-
- // The current mask of |text_store_acp_sink_|.
- DWORD text_store_acp_sink_mask_;
-
- // HWND of the current view window which is set in SetFocusedTextInputClient.
- HWND window_handle_;
-
- // Current TextInputClient which is set in SetFocusedTextInputClient.
- TextInputClient* text_input_client_;
-
- // |string_buffer_| contains committed string and composition string.
- // Example: "aoi" is committed, and "umi" is under composition.
- // |string_buffer_|: "aoiumi"
- // |committed_size_|: 3
- string16 string_buffer_;
- size_t committed_size_;
-
- // |selection_start_| and |selection_end_| indicates the selection range.
- // Example: "iue" is selected
- // |string_buffer_|: "aiueo"
- // |selection_.start()|: 1
- // |selection_.end()|: 4
- gfx::Range selection_;
-
- // |start_offset| and |end_offset| of |composition_undelines_| indicates
- // the offsets in |string_buffer_|.
- // Example: "aoi" is committed. There are two underlines in "umi" and "no".
- // |string_buffer_|: "aoiumino"
- // |committed_size_|: 3
- // composition_undelines_.underlines[0].start_offset: 3
- // composition_undelines_.underlines[0].end_offset: 6
- // composition_undelines_.underlines[1].start_offset: 6
- // composition_undelines_.underlines[1].end_offset: 8
- CompositionUnderlines composition_undelines_;
-
- // |edit_flag_| indicates that the status is edited during
- // ITextStoreACPSink::OnLockGranted().
- bool edit_flag_;
-
- // The type of current lock.
- // 0: No lock.
- // TS_LF_READ: read-only lock.
- // TS_LF_READWRITE: read/write lock.
- DWORD current_lock_type_;
-
- // Queue of the lock request used in RequestLock().
- std::deque<DWORD> lock_queue_;
-
- // Category manager and Display attribute manager are used to obtain the
- // attributes of the composition string.
- base::win::ScopedComPtr<ITfCategoryMgr> category_manager_;
- base::win::ScopedComPtr<ITfDisplayAttributeMgr> display_attribute_manager_;
-
- DISALLOW_COPY_AND_ASSIGN(TSFTextStore);
-};
-
-} // namespace ui
-
-#endif // UI_BASE_IME_WIN_TSF_TEXT_STORE_H_
diff --git a/chromium/ui/base/ime/win/tsf_text_store_unittest.cc b/chromium/ui/base/ime/win/tsf_text_store_unittest.cc
deleted file mode 100644
index 33812a4e01e..00000000000
--- a/chromium/ui/base/ime/win/tsf_text_store_unittest.cc
+++ /dev/null
@@ -1,1302 +0,0 @@
-// Copyright (c) 2012 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.
-
-#include "ui/base/ime/win/tsf_text_store.h"
-
-#include <initguid.h> // for GUID_NULL and GUID_PROP_INPUTSCOPE
-#include <InputScope.h>
-#include <OleCtl.h>
-
-#include "base/memory/ref_counted.h"
-#include "base/win/scoped_com_initializer.h"
-#include "base/win/scoped_variant.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "ui/base/ime/text_input_client.h"
-#include "ui/gfx/rect.h"
-
-using testing::_;
-using testing::Invoke;
-using testing::Return;
-
-namespace ui {
-namespace {
-
-class MockTextInputClient : public TextInputClient {
- public:
- ~MockTextInputClient() {}
- MOCK_METHOD1(SetCompositionText, void(const ui::CompositionText&));
- MOCK_METHOD0(ConfirmCompositionText, void());
- MOCK_METHOD0(ClearCompositionText, void());
- MOCK_METHOD1(InsertText, void(const string16&));
- MOCK_METHOD2(InsertChar, void(char16, int));
- MOCK_CONST_METHOD0(GetAttachedWindow, gfx::NativeWindow());
- MOCK_CONST_METHOD0(GetTextInputType, ui::TextInputType());
- MOCK_CONST_METHOD0(GetTextInputMode, ui::TextInputMode());
- MOCK_CONST_METHOD0(CanComposeInline, bool());
- MOCK_CONST_METHOD0(GetCaretBounds, gfx::Rect());
- MOCK_CONST_METHOD2(GetCompositionCharacterBounds, bool(uint32, gfx::Rect*));
- MOCK_CONST_METHOD0(HasCompositionText, bool());
- MOCK_CONST_METHOD1(GetTextRange, bool(gfx::Range*));
- MOCK_CONST_METHOD1(GetCompositionTextRange, bool(gfx::Range*));
- MOCK_CONST_METHOD1(GetSelectionRange, bool(gfx::Range*));
- MOCK_METHOD1(SetSelectionRange, bool(const gfx::Range&));
- MOCK_METHOD1(DeleteRange, bool(const gfx::Range&));
- MOCK_CONST_METHOD2(GetTextFromRange, bool(const gfx::Range&, string16*));
- MOCK_METHOD0(OnInputMethodChanged, void());
- MOCK_METHOD1(ChangeTextDirectionAndLayoutAlignment,
- bool(base::i18n::TextDirection));
- MOCK_METHOD2(ExtendSelectionAndDelete, void(size_t, size_t));
- MOCK_METHOD1(EnsureCaretInRect, void(const gfx::Rect&));
- MOCK_METHOD0(OnCandidateWindowShown, void());
- MOCK_METHOD0(OnCandidateWindowUpdated, void());
- MOCK_METHOD0(OnCandidateWindowHidden, void());
-};
-
-class MockStoreACPSink : public ITextStoreACPSink {
- public:
- MockStoreACPSink() : ref_count_(0) {}
-
- // IUnknown
- virtual ULONG STDMETHODCALLTYPE AddRef() OVERRIDE {
- return InterlockedIncrement(&ref_count_);
- }
- virtual ULONG STDMETHODCALLTYPE Release() OVERRIDE {
- const LONG count = InterlockedDecrement(&ref_count_);
- if (!count) {
- delete this;
- return 0;
- }
- return static_cast<ULONG>(count);
- }
- virtual HRESULT STDMETHODCALLTYPE QueryInterface(
- REFIID iid, void** report) OVERRIDE {
- if (iid == IID_IUnknown || iid == IID_ITextStoreACPSink) {
- *report = static_cast<ITextStoreACPSink*>(this);
- } else {
- *report = NULL;
- return E_NOINTERFACE;
- }
- AddRef();
- return S_OK;
- }
-
- // ITextStoreACPSink
- MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, OnTextChange,
- HRESULT(DWORD, const TS_TEXTCHANGE*));
- MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, OnSelectionChange,
- HRESULT());
- MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, OnLayoutChange,
- HRESULT(TsLayoutCode, TsViewCookie));
- MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, OnStatusChange,
- HRESULT(DWORD));
- MOCK_METHOD4_WITH_CALLTYPE(STDMETHODCALLTYPE, OnAttrsChange,
- HRESULT(LONG, LONG, ULONG, const TS_ATTRID*));
- MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, OnLockGranted,
- HRESULT(DWORD));
- MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, OnStartEditTransaction,
- HRESULT());
- MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, OnEndEditTransaction,
- HRESULT());
-
- private:
- virtual ~MockStoreACPSink() {}
-
- volatile LONG ref_count_;
-};
-
-const HWND kWindowHandle = reinterpret_cast<HWND>(1);
-
-} // namespace
-
-class TSFTextStoreTest : public testing::Test {
- protected:
- virtual void SetUp() OVERRIDE {
- text_store_ = new TSFTextStore();
- sink_ = new MockStoreACPSink();
- EXPECT_EQ(S_OK, text_store_->AdviseSink(IID_ITextStoreACPSink,
- sink_, TS_AS_ALL_SINKS));
- text_store_->SetFocusedTextInputClient(kWindowHandle,
- &text_input_client_);
- }
-
- virtual void TearDown() OVERRIDE {
- EXPECT_EQ(S_OK, text_store_->UnadviseSink(sink_));
- sink_ = NULL;
- text_store_ = NULL;
- }
-
- // Accessors to the internal state of TSFTextStore.
- string16* string_buffer() { return &text_store_->string_buffer_; }
- size_t* committed_size() { return &text_store_->committed_size_; }
-
- base::win::ScopedCOMInitializer com_initializer_;
- MockTextInputClient text_input_client_;
- scoped_refptr<TSFTextStore> text_store_;
- scoped_refptr<MockStoreACPSink> sink_;
-};
-
-class TSFTextStoreTestCallback {
- public:
- explicit TSFTextStoreTestCallback(TSFTextStore* text_store)
- : text_store_(text_store) {
- CHECK(text_store_);
- }
- virtual ~TSFTextStoreTestCallback() {}
-
- protected:
- // Accessors to the internal state of TSFTextStore.
- bool* edit_flag() { return &text_store_->edit_flag_; }
- string16* string_buffer() { return &text_store_->string_buffer_; }
- size_t* committed_size() { return &text_store_->committed_size_; }
- gfx::Range* selection() { return &text_store_->selection_; }
- CompositionUnderlines* composition_undelines() {
- return &text_store_->composition_undelines_;
- }
-
- void SetInternalState(const string16& new_string_buffer,
- LONG new_committed_size, LONG new_selection_start,
- LONG new_selection_end) {
- ASSERT_LE(0, new_committed_size);
- ASSERT_LE(new_committed_size, new_selection_start);
- ASSERT_LE(new_selection_start, new_selection_end);
- ASSERT_LE(new_selection_end, static_cast<LONG>(new_string_buffer.size()));
- *string_buffer() = new_string_buffer;
- *committed_size() = new_committed_size;
- selection()->set_start(new_selection_start);
- selection()->set_end(new_selection_end);
- }
-
- bool HasReadLock() const { return text_store_->HasReadLock(); }
- bool HasReadWriteLock() const { return text_store_->HasReadWriteLock(); }
-
- void GetSelectionTest(LONG expected_acp_start, LONG expected_acp_end) {
- TS_SELECTION_ACP selection = {};
- ULONG fetched = 0;
- EXPECT_EQ(S_OK, text_store_->GetSelection(0, 1, &selection, &fetched));
- EXPECT_EQ(1, fetched);
- EXPECT_EQ(expected_acp_start, selection.acpStart);
- EXPECT_EQ(expected_acp_end, selection.acpEnd);
- }
-
- void SetSelectionTest(LONG acp_start, LONG acp_end, HRESULT expected_result) {
- TS_SELECTION_ACP selection = {};
- selection.acpStart = acp_start;
- selection.acpEnd = acp_end;
- selection.style.ase = TS_AE_NONE;
- selection.style.fInterimChar = 0;
- EXPECT_EQ(expected_result, text_store_->SetSelection(1, &selection));
- if (expected_result == S_OK) {
- GetSelectionTest(acp_start, acp_end);
- }
- }
-
- void SetTextTest(LONG acp_start, LONG acp_end,
- const string16& text, HRESULT error_code) {
- TS_TEXTCHANGE change = {};
- ASSERT_EQ(error_code,
- text_store_->SetText(0, acp_start, acp_end,
- text.c_str(), text.size(), &change));
- if (error_code == S_OK) {
- EXPECT_EQ(acp_start, change.acpStart);
- EXPECT_EQ(acp_end, change.acpOldEnd);
- EXPECT_EQ(acp_start + text.size(), change.acpNewEnd);
- }
- }
-
- void GetTextTest(LONG acp_start, LONG acp_end,
- const string16& expected_string,
- LONG expected_next_acp) {
- wchar_t buffer[1024] = {};
- ULONG text_buffer_copied = 0;
- TS_RUNINFO run_info = {};
- ULONG run_info_buffer_copied = 0;
- LONG next_acp = 0;
- ASSERT_EQ(S_OK,
- text_store_->GetText(acp_start, acp_end, buffer, 1024,
- &text_buffer_copied,
- &run_info, 1, &run_info_buffer_copied,
- &next_acp));
- ASSERT_EQ(expected_string.size(), text_buffer_copied);
- EXPECT_EQ(expected_string, string16(buffer, buffer + text_buffer_copied));
- EXPECT_EQ(1, run_info_buffer_copied);
- EXPECT_EQ(expected_string.size(), run_info.uCount);
- EXPECT_EQ(TS_RT_PLAIN, run_info.type);
- EXPECT_EQ(expected_next_acp, next_acp);
- }
-
- void GetTextErrorTest(LONG acp_start, LONG acp_end, HRESULT error_code) {
- wchar_t buffer[1024] = {};
- ULONG text_buffer_copied = 0;
- TS_RUNINFO run_info = {};
- ULONG run_info_buffer_copied = 0;
- LONG next_acp = 0;
- EXPECT_EQ(error_code,
- text_store_->GetText(acp_start, acp_end, buffer, 1024,
- &text_buffer_copied,
- &run_info, 1, &run_info_buffer_copied,
- &next_acp));
- }
-
- void InsertTextAtSelectionTest(const wchar_t* buffer, ULONG buffer_size,
- LONG expected_start, LONG expected_end,
- LONG expected_change_start,
- LONG expected_change_old_end,
- LONG expected_change_new_end) {
- LONG start = 0;
- LONG end = 0;
- TS_TEXTCHANGE change = {};
- EXPECT_EQ(S_OK,
- text_store_->InsertTextAtSelection(0, buffer, buffer_size,
- &start, &end, &change));
- EXPECT_EQ(expected_start, start);
- EXPECT_EQ(expected_end, end);
- EXPECT_EQ(expected_change_start, change.acpStart);
- EXPECT_EQ(expected_change_old_end, change.acpOldEnd);
- EXPECT_EQ(expected_change_new_end, change.acpNewEnd);
- }
-
- void InsertTextAtSelectionQueryOnlyTest(const wchar_t* buffer,
- ULONG buffer_size,
- LONG expected_start,
- LONG expected_end) {
- LONG start = 0;
- LONG end = 0;
- EXPECT_EQ(S_OK,
- text_store_->InsertTextAtSelection(TS_IAS_QUERYONLY, buffer,
- buffer_size, &start, &end,
- NULL));
- EXPECT_EQ(expected_start, start);
- EXPECT_EQ(expected_end, end);
- }
-
- void GetTextExtTest(TsViewCookie view_cookie, LONG acp_start, LONG acp_end,
- LONG expected_left, LONG expected_top,
- LONG expected_right, LONG expected_bottom) {
- RECT rect = {};
- BOOL clipped = FALSE;
- EXPECT_EQ(S_OK, text_store_->GetTextExt(view_cookie, acp_start, acp_end,
- &rect, &clipped));
- EXPECT_EQ(expected_left, rect.left);
- EXPECT_EQ(expected_top, rect.top);
- EXPECT_EQ(expected_right, rect.right);
- EXPECT_EQ(expected_bottom, rect.bottom);
- EXPECT_EQ(FALSE, clipped);
- }
-
- void GetTextExtNoLayoutTest(TsViewCookie view_cookie, LONG acp_start,
- LONG acp_end) {
- RECT rect = {};
- BOOL clipped = FALSE;
- EXPECT_EQ(TS_E_NOLAYOUT,
- text_store_->GetTextExt(view_cookie, acp_start, acp_end,
- &rect, &clipped));
- }
-
- scoped_refptr<TSFTextStore> text_store_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TSFTextStoreTestCallback);
-};
-
-namespace {
-
-const HRESULT kInvalidResult = 0x12345678;
-
-TEST_F(TSFTextStoreTest, GetStatusTest) {
- TS_STATUS status = {};
- EXPECT_EQ(S_OK, text_store_->GetStatus(&status));
- EXPECT_EQ(0, status.dwDynamicFlags);
- EXPECT_EQ(TS_SS_TRANSITORY | TS_SS_NOHIDDENTEXT, status.dwStaticFlags);
-}
-
-TEST_F(TSFTextStoreTest, QueryInsertTest) {
- LONG result_start = 0;
- LONG result_end = 0;
- *string_buffer() = L"";
- *committed_size() = 0;
- EXPECT_EQ(E_INVALIDARG,
- text_store_->QueryInsert(0, 0, 0, NULL, &result_end));
- EXPECT_EQ(E_INVALIDARG,
- text_store_->QueryInsert(0, 0, 0, &result_start, NULL));
- EXPECT_EQ(S_OK,
- text_store_->QueryInsert(0, 0, 0, &result_start, &result_end));
- EXPECT_EQ(0, result_start);
- EXPECT_EQ(0, result_end);
- *string_buffer() = L"1234";
- *committed_size() = 1;
- EXPECT_EQ(S_OK,
- text_store_->QueryInsert(0, 1, 0, &result_start, &result_end));
- EXPECT_EQ(1, result_start);
- EXPECT_EQ(1, result_end);
- EXPECT_EQ(E_INVALIDARG,
- text_store_->QueryInsert(1, 0, 0, &result_start, &result_end));
- EXPECT_EQ(S_OK,
- text_store_->QueryInsert(2, 2, 0, &result_start, &result_end));
- EXPECT_EQ(2, result_start);
- EXPECT_EQ(2, result_end);
- EXPECT_EQ(S_OK,
- text_store_->QueryInsert(2, 3, 0, &result_start, &result_end));
- EXPECT_EQ(2, result_start);
- EXPECT_EQ(3, result_end);
- EXPECT_EQ(E_INVALIDARG,
- text_store_->QueryInsert(3, 2, 0, &result_start, &result_end));
- EXPECT_EQ(S_OK,
- text_store_->QueryInsert(3, 4, 0, &result_start, &result_end));
- EXPECT_EQ(3, result_start);
- EXPECT_EQ(4, result_end);
- EXPECT_EQ(S_OK,
- text_store_->QueryInsert(3, 5, 0, &result_start, &result_end));
- EXPECT_EQ(3, result_start);
- EXPECT_EQ(4, result_end);
-}
-
-class SyncRequestLockTestCallback : public TSFTextStoreTestCallback {
- public:
- explicit SyncRequestLockTestCallback(TSFTextStore* text_store)
- : TSFTextStoreTestCallback(text_store) {}
-
- HRESULT LockGranted1(DWORD flags) {
- EXPECT_TRUE(HasReadLock());
- EXPECT_FALSE(HasReadWriteLock());
- return S_OK;
- }
-
- HRESULT LockGranted2(DWORD flags) {
- EXPECT_TRUE(HasReadLock());
- EXPECT_TRUE(HasReadWriteLock());
- return S_OK;
- }
-
- HRESULT LockGranted3(DWORD flags) {
- EXPECT_TRUE(HasReadLock());
- EXPECT_FALSE(HasReadWriteLock());
- HRESULT result = kInvalidResult;
- EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ | TS_LF_SYNC, &result));
- EXPECT_EQ(TS_E_SYNCHRONOUS, result);
- return S_OK;
- }
-
- HRESULT LockGranted4(DWORD flags) {
- EXPECT_TRUE(HasReadLock());
- EXPECT_FALSE(HasReadWriteLock());
- HRESULT result = kInvalidResult;
- EXPECT_EQ(S_OK,
- text_store_->RequestLock(TS_LF_READWRITE | TS_LF_SYNC, &result));
- EXPECT_EQ(TS_E_SYNCHRONOUS, result);
- return S_OK;
- }
-
- HRESULT LockGranted5(DWORD flags) {
- EXPECT_TRUE(HasReadLock());
- EXPECT_TRUE(HasReadWriteLock());
- HRESULT result = kInvalidResult;
- EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ | TS_LF_SYNC, &result));
- EXPECT_EQ(TS_E_SYNCHRONOUS, result);
- return S_OK;
- }
-
- HRESULT LockGranted6(DWORD flags) {
- EXPECT_TRUE(HasReadLock());
- EXPECT_TRUE(HasReadWriteLock());
- HRESULT result = kInvalidResult;
- EXPECT_EQ(S_OK,
- text_store_->RequestLock(TS_LF_READWRITE | TS_LF_SYNC, &result));
- EXPECT_EQ(TS_E_SYNCHRONOUS, result);
- return S_OK;
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(SyncRequestLockTestCallback);
-};
-
-TEST_F(TSFTextStoreTest, SynchronousRequestLockTest) {
- SyncRequestLockTestCallback callback(text_store_);
- EXPECT_CALL(*sink_, OnLockGranted(_))
- .WillOnce(Invoke(&callback, &SyncRequestLockTestCallback::LockGranted1))
- .WillOnce(Invoke(&callback, &SyncRequestLockTestCallback::LockGranted2))
- .WillOnce(Invoke(&callback, &SyncRequestLockTestCallback::LockGranted3))
- .WillOnce(Invoke(&callback, &SyncRequestLockTestCallback::LockGranted4))
- .WillOnce(Invoke(&callback, &SyncRequestLockTestCallback::LockGranted5))
- .WillOnce(Invoke(&callback, &SyncRequestLockTestCallback::LockGranted6));
-
- HRESULT result = kInvalidResult;
- EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ | TS_LF_SYNC, &result));
- EXPECT_EQ(S_OK, result);
- result = kInvalidResult;
- EXPECT_EQ(S_OK,
- text_store_->RequestLock(TS_LF_READWRITE | TS_LF_SYNC, &result));
- EXPECT_EQ(S_OK, result);
-
- EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ | TS_LF_SYNC, &result));
- EXPECT_EQ(S_OK, result);
- result = kInvalidResult;
- EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ | TS_LF_SYNC, &result));
- EXPECT_EQ(S_OK, result);
-
- result = kInvalidResult;
- EXPECT_EQ(S_OK,
- text_store_->RequestLock(TS_LF_READWRITE | TS_LF_SYNC, &result));
- EXPECT_EQ(S_OK, result);
- result = kInvalidResult;
- EXPECT_EQ(S_OK,
- text_store_->RequestLock(TS_LF_READWRITE | TS_LF_SYNC, &result));
- EXPECT_EQ(S_OK, result);
-}
-
-class AsyncRequestLockTestCallback : public TSFTextStoreTestCallback {
- public:
- explicit AsyncRequestLockTestCallback(TSFTextStore* text_store)
- : TSFTextStoreTestCallback(text_store),
- state_(0) {}
-
- HRESULT LockGranted1(DWORD flags) {
- EXPECT_EQ(0, state_);
- state_ = 1;
- EXPECT_TRUE(HasReadLock());
- EXPECT_FALSE(HasReadWriteLock());
- HRESULT result = kInvalidResult;
- EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ, &result));
- EXPECT_EQ(TS_S_ASYNC, result);
- EXPECT_EQ(1, state_);
- state_ = 2;
- return S_OK;
- }
-
- HRESULT LockGranted2(DWORD flags) {
- EXPECT_EQ(2, state_);
- EXPECT_TRUE(HasReadLock());
- EXPECT_FALSE(HasReadWriteLock());
- HRESULT result = kInvalidResult;
- EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
- EXPECT_EQ(TS_S_ASYNC, result);
- EXPECT_EQ(2, state_);
- state_ = 3;
- return S_OK;
- }
-
- HRESULT LockGranted3(DWORD flags) {
- EXPECT_EQ(3, state_);
- EXPECT_TRUE(HasReadLock());
- EXPECT_TRUE(HasReadWriteLock());
- HRESULT result = kInvalidResult;
- EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
- EXPECT_EQ(TS_S_ASYNC, result);
- EXPECT_EQ(3, state_);
- state_ = 4;
- return S_OK;
- }
-
- HRESULT LockGranted4(DWORD flags) {
- EXPECT_EQ(4, state_);
- EXPECT_TRUE(HasReadLock());
- EXPECT_TRUE(HasReadWriteLock());
- HRESULT result = kInvalidResult;
- EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ, &result));
- EXPECT_EQ(TS_S_ASYNC, result);
- EXPECT_EQ(4, state_);
- state_ = 5;
- return S_OK;
- }
-
- HRESULT LockGranted5(DWORD flags) {
- EXPECT_EQ(5, state_);
- EXPECT_TRUE(HasReadLock());
- EXPECT_FALSE(HasReadWriteLock());
- state_ = 6;
- return S_OK;
- }
-
- private:
- int state_;
-
- DISALLOW_COPY_AND_ASSIGN(AsyncRequestLockTestCallback);
-};
-
-TEST_F(TSFTextStoreTest, AsynchronousRequestLockTest) {
- AsyncRequestLockTestCallback callback(text_store_);
- EXPECT_CALL(*sink_, OnLockGranted(_))
- .WillOnce(Invoke(&callback, &AsyncRequestLockTestCallback::LockGranted1))
- .WillOnce(Invoke(&callback, &AsyncRequestLockTestCallback::LockGranted2))
- .WillOnce(Invoke(&callback, &AsyncRequestLockTestCallback::LockGranted3))
- .WillOnce(Invoke(&callback, &AsyncRequestLockTestCallback::LockGranted4))
- .WillOnce(Invoke(&callback, &AsyncRequestLockTestCallback::LockGranted5));
-
- HRESULT result = kInvalidResult;
- EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ, &result));
- EXPECT_EQ(S_OK, result);
-}
-
-class RequestLockTextChangeTestCallback : public TSFTextStoreTestCallback {
- public:
- explicit RequestLockTextChangeTestCallback(TSFTextStore* text_store)
- : TSFTextStoreTestCallback(text_store),
- state_(0) {}
-
- HRESULT LockGranted1(DWORD flags) {
- EXPECT_EQ(0, state_);
- state_ = 1;
- EXPECT_TRUE(HasReadLock());
- EXPECT_TRUE(HasReadWriteLock());
-
- *edit_flag() = true;
- SetInternalState(L"012345", 6, 6, 6);
- composition_undelines()->clear();
-
- state_ = 2;
- return S_OK;
- }
-
- void InsertText(const string16& text) {
- EXPECT_EQ(2, state_);
- EXPECT_EQ(L"012345", text);
- state_ = 3;
- }
-
- void SetCompositionText(const ui::CompositionText& composition) {
- EXPECT_EQ(3, state_);
- EXPECT_EQ(L"", composition.text);
- EXPECT_EQ(0, composition.selection.start());
- EXPECT_EQ(0, composition.selection.end());
- EXPECT_EQ(0, composition.underlines.size());
- state_ = 4;
- }
-
- HRESULT OnTextChange(DWORD flags, const TS_TEXTCHANGE* change) {
- EXPECT_EQ(4, state_);
- HRESULT result = kInvalidResult;
- state_ = 5;
- EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
- EXPECT_EQ(S_OK, result);
- EXPECT_EQ(6, state_);
- state_ = 7;
- return S_OK;
- }
-
- HRESULT LockGranted2(DWORD flags) {
- EXPECT_EQ(5, state_);
- EXPECT_TRUE(HasReadLock());
- EXPECT_TRUE(HasReadWriteLock());
- state_ = 6;
- return S_OK;
- }
-
- private:
- int state_;
-
- DISALLOW_COPY_AND_ASSIGN(RequestLockTextChangeTestCallback);
-};
-
-TEST_F(TSFTextStoreTest, RequestLockOnTextChangeTest) {
- RequestLockTextChangeTestCallback callback(text_store_);
- EXPECT_CALL(*sink_, OnLockGranted(_))
- .WillOnce(Invoke(&callback,
- &RequestLockTextChangeTestCallback::LockGranted1))
- .WillOnce(Invoke(&callback,
- &RequestLockTextChangeTestCallback::LockGranted2));
-
- EXPECT_CALL(*sink_, OnSelectionChange())
- .WillOnce(Return(S_OK));
- EXPECT_CALL(*sink_, OnLayoutChange(_, _))
- .WillOnce(Return(S_OK));
- EXPECT_CALL(*sink_, OnTextChange(_, _))
- .WillOnce(Invoke(&callback,
- &RequestLockTextChangeTestCallback::OnTextChange));
- EXPECT_CALL(text_input_client_, InsertText(_))
- .WillOnce(Invoke(&callback,
- &RequestLockTextChangeTestCallback::InsertText));
- EXPECT_CALL(text_input_client_, SetCompositionText(_))
- .WillOnce(Invoke(&callback,
- &RequestLockTextChangeTestCallback::SetCompositionText));
-
- HRESULT result = kInvalidResult;
- EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
- EXPECT_EQ(S_OK, result);
-}
-
-class SelectionTestCallback : public TSFTextStoreTestCallback {
- public:
- explicit SelectionTestCallback(TSFTextStore* text_store)
- : TSFTextStoreTestCallback(text_store) {}
-
- HRESULT ReadLockGranted(DWORD flags) {
- SetInternalState(L"", 0, 0, 0);
-
- GetSelectionTest(0, 0);
- SetSelectionTest(0, 0, TF_E_NOLOCK);
-
- SetInternalState(L"012345", 0, 0, 3);
-
- GetSelectionTest(0, 3);
- SetSelectionTest(0, 0, TF_E_NOLOCK);
-
- return S_OK;
- }
-
- HRESULT ReadWriteLockGranted(DWORD flags) {
- SetInternalState(L"", 0, 0, 0);
-
- SetSelectionTest(0, 0, S_OK);
- GetSelectionTest(0, 0);
- SetSelectionTest(0, 1, TF_E_INVALIDPOS);
- SetSelectionTest(1, 0, TF_E_INVALIDPOS);
- SetSelectionTest(1, 1, TF_E_INVALIDPOS);
-
- SetInternalState(L"0123456", 3, 3, 3);
-
- SetSelectionTest(0, 0, TF_E_INVALIDPOS);
- SetSelectionTest(0, 1, TF_E_INVALIDPOS);
- SetSelectionTest(0, 3, TF_E_INVALIDPOS);
- SetSelectionTest(0, 6, TF_E_INVALIDPOS);
- SetSelectionTest(0, 7, TF_E_INVALIDPOS);
- SetSelectionTest(0, 8, TF_E_INVALIDPOS);
-
- SetSelectionTest(1, 0, TF_E_INVALIDPOS);
- SetSelectionTest(1, 1, TF_E_INVALIDPOS);
- SetSelectionTest(1, 3, TF_E_INVALIDPOS);
- SetSelectionTest(1, 6, TF_E_INVALIDPOS);
- SetSelectionTest(1, 7, TF_E_INVALIDPOS);
- SetSelectionTest(1, 8, TF_E_INVALIDPOS);
-
- SetSelectionTest(3, 0, TF_E_INVALIDPOS);
- SetSelectionTest(3, 1, TF_E_INVALIDPOS);
- SetSelectionTest(3, 3, S_OK);
- SetSelectionTest(3, 6, S_OK);
- SetSelectionTest(3, 7, S_OK);
- SetSelectionTest(3, 8, TF_E_INVALIDPOS);
-
- SetSelectionTest(6, 0, TF_E_INVALIDPOS);
- SetSelectionTest(6, 1, TF_E_INVALIDPOS);
- SetSelectionTest(6, 3, TF_E_INVALIDPOS);
- SetSelectionTest(6, 6, S_OK);
- SetSelectionTest(6, 7, S_OK);
- SetSelectionTest(6, 8, TF_E_INVALIDPOS);
-
- SetSelectionTest(7, 0, TF_E_INVALIDPOS);
- SetSelectionTest(7, 1, TF_E_INVALIDPOS);
- SetSelectionTest(7, 3, TF_E_INVALIDPOS);
- SetSelectionTest(7, 6, TF_E_INVALIDPOS);
- SetSelectionTest(7, 7, S_OK);
- SetSelectionTest(7, 8, TF_E_INVALIDPOS);
-
- SetSelectionTest(8, 0, TF_E_INVALIDPOS);
- SetSelectionTest(8, 1, TF_E_INVALIDPOS);
- SetSelectionTest(8, 3, TF_E_INVALIDPOS);
- SetSelectionTest(8, 6, TF_E_INVALIDPOS);
- SetSelectionTest(8, 7, TF_E_INVALIDPOS);
- SetSelectionTest(8, 8, TF_E_INVALIDPOS);
-
- return S_OK;
- }
-};
-
-TEST_F(TSFTextStoreTest, SetGetSelectionTest) {
- SelectionTestCallback callback(text_store_);
- EXPECT_CALL(*sink_, OnLockGranted(_))
- .WillOnce(Invoke(&callback, &SelectionTestCallback::ReadLockGranted))
- .WillOnce(Invoke(&callback,
- &SelectionTestCallback::ReadWriteLockGranted));
-
- TS_SELECTION_ACP selection_buffer = {};
- ULONG fetched_count = 0;
- EXPECT_EQ(TS_E_NOLOCK,
- text_store_->GetSelection(0, 1, &selection_buffer,
- &fetched_count));
-
- HRESULT result = kInvalidResult;
- EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ, &result));
- EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
-}
-
-class SetGetTextTestCallback : public TSFTextStoreTestCallback {
- public:
- explicit SetGetTextTestCallback(TSFTextStore* text_store)
- : TSFTextStoreTestCallback(text_store) {}
-
- HRESULT ReadLockGranted(DWORD flags) {
- SetTextTest(0, 0, L"", TF_E_NOLOCK);
-
- GetTextTest(0, -1, L"", 0);
- GetTextTest(0, 0, L"", 0);
- GetTextErrorTest(0, 1, TF_E_INVALIDPOS);
-
- SetInternalState(L"0123456", 3, 3, 3);
-
- GetTextErrorTest(-1, -1, TF_E_INVALIDPOS);
- GetTextErrorTest(-1, 0, TF_E_INVALIDPOS);
- GetTextErrorTest(-1, 1, TF_E_INVALIDPOS);
- GetTextErrorTest(-1, 3, TF_E_INVALIDPOS);
- GetTextErrorTest(-1, 6, TF_E_INVALIDPOS);
- GetTextErrorTest(-1, 7, TF_E_INVALIDPOS);
- GetTextErrorTest(-1, 8, TF_E_INVALIDPOS);
-
- GetTextTest(0, -1, L"0123456", 7);
- GetTextTest(0, 0, L"", 0);
- GetTextTest(0, 1, L"0", 1);
- GetTextTest(0, 3, L"012", 3);
- GetTextTest(0, 6, L"012345", 6);
- GetTextTest(0, 7, L"0123456", 7);
- GetTextErrorTest(0, 8, TF_E_INVALIDPOS);
-
- GetTextTest(1, -1, L"123456", 7);
- GetTextErrorTest(1, 0, TF_E_INVALIDPOS);
- GetTextTest(1, 1, L"", 1);
- GetTextTest(1, 3, L"12", 3);
- GetTextTest(1, 6, L"12345", 6);
- GetTextTest(1, 7, L"123456", 7);
- GetTextErrorTest(1, 8, TF_E_INVALIDPOS);
-
- GetTextTest(3, -1, L"3456", 7);
- GetTextErrorTest(3, 0, TF_E_INVALIDPOS);
- GetTextErrorTest(3, 1, TF_E_INVALIDPOS);
- GetTextTest(3, 3, L"", 3);
- GetTextTest(3, 6, L"345", 6);
- GetTextTest(3, 7, L"3456", 7);
- GetTextErrorTest(3, 8, TF_E_INVALIDPOS);
-
- GetTextTest(6, -1, L"6", 7);
- GetTextErrorTest(6, 0, TF_E_INVALIDPOS);
- GetTextErrorTest(6, 1, TF_E_INVALIDPOS);
- GetTextErrorTest(6, 3, TF_E_INVALIDPOS);
- GetTextTest(6, 6, L"", 6);
- GetTextTest(6, 7, L"6", 7);
- GetTextErrorTest(6, 8, TF_E_INVALIDPOS);
-
- GetTextTest(7, -1, L"", 7);
- GetTextErrorTest(7, 0, TF_E_INVALIDPOS);
- GetTextErrorTest(7, 1, TF_E_INVALIDPOS);
- GetTextErrorTest(7, 3, TF_E_INVALIDPOS);
- GetTextErrorTest(7, 6, TF_E_INVALIDPOS);
- GetTextTest(7, 7, L"", 7);
- GetTextErrorTest(7, 8, TF_E_INVALIDPOS);
-
- GetTextErrorTest(8, -1, TF_E_INVALIDPOS);
- GetTextErrorTest(8, 0, TF_E_INVALIDPOS);
- GetTextErrorTest(8, 1, TF_E_INVALIDPOS);
- GetTextErrorTest(8, 3, TF_E_INVALIDPOS);
- GetTextErrorTest(8, 6, TF_E_INVALIDPOS);
- GetTextErrorTest(8, 7, TF_E_INVALIDPOS);
- GetTextErrorTest(8, 8, TF_E_INVALIDPOS);
-
- return S_OK;
- }
-
- HRESULT ReadWriteLockGranted(DWORD flags) {
- SetInternalState(L"", 0, 0, 0);
- SetTextTest(0, 0, L"", S_OK);
-
- SetInternalState(L"", 0, 0, 0);
- SetTextTest(0, 1, L"", TS_E_INVALIDPOS);
-
- SetInternalState(L"0123456", 3, 3, 3);
-
- SetTextTest(0, 0, L"", TS_E_INVALIDPOS);
- SetTextTest(0, 1, L"", TS_E_INVALIDPOS);
- SetTextTest(0, 3, L"", TS_E_INVALIDPOS);
- SetTextTest(0, 6, L"", TS_E_INVALIDPOS);
- SetTextTest(0, 7, L"", TS_E_INVALIDPOS);
- SetTextTest(0, 8, L"", TS_E_INVALIDPOS);
-
- SetTextTest(1, 0, L"", TS_E_INVALIDPOS);
- SetTextTest(1, 1, L"", TS_E_INVALIDPOS);
- SetTextTest(1, 3, L"", TS_E_INVALIDPOS);
- SetTextTest(1, 6, L"", TS_E_INVALIDPOS);
- SetTextTest(1, 7, L"", TS_E_INVALIDPOS);
- SetTextTest(1, 8, L"", TS_E_INVALIDPOS);
-
- SetTextTest(3, 0, L"", TS_E_INVALIDPOS);
- SetTextTest(3, 1, L"", TS_E_INVALIDPOS);
-
- SetTextTest(3, 3, L"", S_OK);
- GetTextTest(0, -1, L"0123456", 7);
- GetSelectionTest(3, 3);
- SetInternalState(L"0123456", 3, 3, 3);
-
- SetTextTest(3, 6, L"", S_OK);
- GetTextTest(0, -1, L"0126", 4);
- GetSelectionTest(3, 3);
- SetInternalState(L"0123456", 3, 3, 3);
-
- SetTextTest(3, 7, L"", S_OK);
- GetTextTest(0, -1, L"012", 3);
- GetSelectionTest(3, 3);
- SetInternalState(L"0123456", 3, 3, 3);
-
- SetTextTest(3, 8, L"", TS_E_INVALIDPOS);
-
- SetTextTest(6, 0, L"", TS_E_INVALIDPOS);
- SetTextTest(6, 1, L"", TS_E_INVALIDPOS);
- SetTextTest(6, 3, L"", TS_E_INVALIDPOS);
-
- SetTextTest(6, 6, L"", S_OK);
- GetTextTest(0, -1, L"0123456", 7);
- GetSelectionTest(6, 6);
- SetInternalState(L"0123456", 3, 3, 3);
-
- SetTextTest(6, 7, L"", S_OK);
- GetTextTest(0, -1, L"012345", 6);
- GetSelectionTest(6, 6);
- SetInternalState(L"0123456", 3, 3, 3);
-
- SetTextTest(6, 8, L"", TS_E_INVALIDPOS);
-
- SetTextTest(7, 0, L"", TS_E_INVALIDPOS);
- SetTextTest(7, 1, L"", TS_E_INVALIDPOS);
- SetTextTest(7, 3, L"", TS_E_INVALIDPOS);
- SetTextTest(7, 6, L"", TS_E_INVALIDPOS);
-
- SetTextTest(7, 7, L"", S_OK);
- GetTextTest(0, -1, L"0123456", 7);
- GetSelectionTest(7, 7);
- SetInternalState(L"0123456", 3, 3, 3);
-
- SetTextTest(7, 8, L"", TS_E_INVALIDPOS);
-
- SetInternalState(L"0123456", 3, 3, 3);
- SetTextTest(3, 3, L"abc", S_OK);
- GetTextTest(0, -1, L"012abc3456", 10);
- GetSelectionTest(3, 6);
-
- SetInternalState(L"0123456", 3, 3, 3);
- SetTextTest(3, 6, L"abc", S_OK);
- GetTextTest(0, -1, L"012abc6", 7);
- GetSelectionTest(3, 6);
-
- SetInternalState(L"0123456", 3, 3, 3);
- SetTextTest(3, 7, L"abc", S_OK);
- GetTextTest(0, -1, L"012abc", 6);
- GetSelectionTest(3, 6);
-
- SetInternalState(L"0123456", 3, 3, 3);
- SetTextTest(6, 6, L"abc", S_OK);
- GetTextTest(0, -1, L"012345abc6", 10);
- GetSelectionTest(6, 9);
-
- SetInternalState(L"0123456", 3, 3, 3);
- SetTextTest(6, 7, L"abc", S_OK);
- GetTextTest(0, -1, L"012345abc", 9);
- GetSelectionTest(6, 9);
-
- SetInternalState(L"0123456", 3, 3, 3);
- SetTextTest(7, 7, L"abc", S_OK);
- GetTextTest(0, -1, L"0123456abc", 10);
- GetSelectionTest(7, 10);
-
- return S_OK;
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(SetGetTextTestCallback);
-};
-
-TEST_F(TSFTextStoreTest, SetGetTextTest) {
- SetGetTextTestCallback callback(text_store_);
- EXPECT_CALL(*sink_, OnLockGranted(_))
- .WillOnce(Invoke(&callback, &SetGetTextTestCallback::ReadLockGranted))
- .WillOnce(Invoke(&callback,
- &SetGetTextTestCallback::ReadWriteLockGranted));
-
- wchar_t buffer[1024] = {};
- ULONG text_buffer_copied = 0;
- TS_RUNINFO run_info = {};
- ULONG run_info_buffer_copied = 0;
- LONG next_acp = 0;
- EXPECT_EQ(TF_E_NOLOCK,
- text_store_->GetText(0, -1, buffer, 1024, &text_buffer_copied,
- &run_info, 1, &run_info_buffer_copied,
- &next_acp));
- TS_TEXTCHANGE change = {};
- EXPECT_EQ(TF_E_NOLOCK, text_store_->SetText(0, 0, 0, L"abc", 3, &change));
-
- HRESULT result = kInvalidResult;
- EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ, &result));
- EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
-}
-
-class InsertTextAtSelectionTestCallback : public TSFTextStoreTestCallback {
- public:
- explicit InsertTextAtSelectionTestCallback(TSFTextStore* text_store)
- : TSFTextStoreTestCallback(text_store) {}
-
- HRESULT ReadLockGranted(DWORD flags) {
- const wchar_t kBuffer[] = L"0123456789";
-
- SetInternalState(L"abcedfg", 0, 0, 0);
- InsertTextAtSelectionQueryOnlyTest(kBuffer, 10, 0, 0);
- GetSelectionTest(0, 0);
- InsertTextAtSelectionQueryOnlyTest(kBuffer, 0, 0, 0);
-
- SetInternalState(L"abcedfg", 0, 2, 5);
- InsertTextAtSelectionQueryOnlyTest(kBuffer, 10, 2, 5);
- GetSelectionTest(2, 5);
- InsertTextAtSelectionQueryOnlyTest(kBuffer, 0, 2, 5);
-
- LONG start = 0;
- LONG end = 0;
- TS_TEXTCHANGE change = {};
- EXPECT_EQ(TS_E_NOLOCK,
- text_store_->InsertTextAtSelection(0, kBuffer, 10,
- &start, &end, &change));
- return S_OK;
- }
-
- HRESULT ReadWriteLockGranted(DWORD flags) {
- SetInternalState(L"abcedfg", 0, 0, 0);
-
- const wchar_t kBuffer[] = L"0123456789";
- InsertTextAtSelectionQueryOnlyTest(kBuffer, 10, 0, 0);
- GetSelectionTest(0, 0);
- InsertTextAtSelectionQueryOnlyTest(kBuffer, 0, 0, 0);
-
- SetInternalState(L"", 0, 0, 0);
- InsertTextAtSelectionTest(kBuffer, 10, 0, 10, 0, 0, 10);
- GetSelectionTest(0, 10);
- GetTextTest(0, -1, L"0123456789", 10);
-
- SetInternalState(L"abcedfg", 0, 0, 0);
- InsertTextAtSelectionTest(kBuffer, 10, 0, 10, 0, 0, 10);
- GetSelectionTest(0, 10);
- GetTextTest(0, -1, L"0123456789abcedfg", 17);
-
- SetInternalState(L"abcedfg", 0, 0, 3);
- InsertTextAtSelectionTest(kBuffer, 0, 0, 0, 0, 3, 0);
- GetSelectionTest(0, 0);
- GetTextTest(0, -1, L"edfg", 4);
-
- SetInternalState(L"abcedfg", 0, 3, 7);
- InsertTextAtSelectionTest(kBuffer, 10, 3, 13, 3, 7, 13);
- GetSelectionTest(3, 13);
- GetTextTest(0, -1, L"abc0123456789", 13);
-
- SetInternalState(L"abcedfg", 0, 7, 7);
- InsertTextAtSelectionTest(kBuffer, 10, 7, 17, 7, 7, 17);
- GetSelectionTest(7, 17);
- GetTextTest(0, -1, L"abcedfg0123456789", 17);
-
- return S_OK;
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(InsertTextAtSelectionTestCallback);
-};
-
-TEST_F(TSFTextStoreTest, InsertTextAtSelectionTest) {
- InsertTextAtSelectionTestCallback callback(text_store_);
- EXPECT_CALL(*sink_, OnLockGranted(_))
- .WillOnce(Invoke(&callback,
- &InsertTextAtSelectionTestCallback::ReadLockGranted))
- .WillOnce(
- Invoke(&callback,
- &InsertTextAtSelectionTestCallback::ReadWriteLockGranted));
-
- HRESULT result = kInvalidResult;
- EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ, &result));
- EXPECT_EQ(S_OK, result);
- result = kInvalidResult;
- EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
- EXPECT_EQ(S_OK, result);
-}
-
-class ScenarioTestCallback : public TSFTextStoreTestCallback {
- public:
- explicit ScenarioTestCallback(TSFTextStore* text_store)
- : TSFTextStoreTestCallback(text_store) {}
-
- HRESULT LockGranted1(DWORD flags) {
- SetSelectionTest(0, 0, S_OK);
-
- SetTextTest(0, 0, L"abc", S_OK);
- SetTextTest(1, 2, L"xyz", S_OK);
-
- GetTextTest(0, -1, L"axyzc", 5);
-
- composition_undelines()->clear();
- CompositionUnderline underline;
- underline.start_offset = 0;
- underline.end_offset = 5;
- underline.color = SK_ColorBLACK;
- underline.thick = false;
- composition_undelines()->push_back(underline);
- *edit_flag() = true;
- *committed_size() = 0;
- return S_OK;
- }
-
- void SetCompositionText1(const ui::CompositionText& composition) {
- EXPECT_EQ(L"axyzc", composition.text);
- EXPECT_EQ(1, composition.selection.start());
- EXPECT_EQ(4, composition.selection.end());
- ASSERT_EQ(1, composition.underlines.size());
- EXPECT_EQ(SK_ColorBLACK, composition.underlines[0].color);
- EXPECT_EQ(0, composition.underlines[0].start_offset);
- EXPECT_EQ(5, composition.underlines[0].end_offset);
- EXPECT_FALSE(composition.underlines[0].thick);
- }
-
- HRESULT LockGranted2(DWORD flags) {
- SetTextTest(3, 4, L"ZCP", S_OK);
- GetTextTest(0, -1, L"axyZCPc", 7);
-
- composition_undelines()->clear();
- CompositionUnderline underline;
- underline.start_offset = 3;
- underline.end_offset = 5;
- underline.color = SK_ColorBLACK;
- underline.thick = true;
- composition_undelines()->push_back(underline);
- underline.start_offset = 5;
- underline.end_offset = 7;
- underline.color = SK_ColorBLACK;
- underline.thick = false;
- composition_undelines()->push_back(underline);
-
- *edit_flag() = true;
- *committed_size() = 3;
-
- return S_OK;
- }
-
- void InsertText2(const string16& text) {
- EXPECT_EQ(L"axy", text);
- }
-
- void SetCompositionText2(const ui::CompositionText& composition) {
- EXPECT_EQ(L"ZCPc", composition.text);
- EXPECT_EQ(0, composition.selection.start());
- EXPECT_EQ(3, composition.selection.end());
- ASSERT_EQ(2, composition.underlines.size());
- EXPECT_EQ(SK_ColorBLACK, composition.underlines[0].color);
- EXPECT_EQ(0, composition.underlines[0].start_offset);
- EXPECT_EQ(2, composition.underlines[0].end_offset);
- EXPECT_TRUE(composition.underlines[0].thick);
- EXPECT_EQ(SK_ColorBLACK, composition.underlines[1].color);
- EXPECT_EQ(2, composition.underlines[1].start_offset);
- EXPECT_EQ(4, composition.underlines[1].end_offset);
- EXPECT_FALSE(composition.underlines[1].thick);
- }
-
- HRESULT LockGranted3(DWORD flags) {
- GetTextTest(0, -1, L"axyZCPc", 7);
-
- composition_undelines()->clear();
- *edit_flag() = true;
- *committed_size() = 7;
-
- return S_OK;
- }
-
- void InsertText3(const string16& text) {
- EXPECT_EQ(L"ZCPc", text);
- }
-
- void SetCompositionText3(const ui::CompositionText& composition) {
- EXPECT_EQ(L"", composition.text);
- EXPECT_EQ(0, composition.selection.start());
- EXPECT_EQ(0, composition.selection.end());
- EXPECT_EQ(0, composition.underlines.size());
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ScenarioTestCallback);
-};
-
-TEST_F(TSFTextStoreTest, ScenarioTest) {
- ScenarioTestCallback callback(text_store_);
- EXPECT_CALL(text_input_client_, SetCompositionText(_))
- .WillOnce(Invoke(&callback, &ScenarioTestCallback::SetCompositionText1))
- .WillOnce(Invoke(&callback, &ScenarioTestCallback::SetCompositionText2))
- .WillOnce(Invoke(&callback, &ScenarioTestCallback::SetCompositionText3));
-
- EXPECT_CALL(text_input_client_, InsertText(_))
- .WillOnce(Invoke(&callback, &ScenarioTestCallback::InsertText2))
- .WillOnce(Invoke(&callback, &ScenarioTestCallback::InsertText3));
-
- EXPECT_CALL(*sink_, OnLockGranted(_))
- .WillOnce(Invoke(&callback, &ScenarioTestCallback::LockGranted1))
- .WillOnce(Invoke(&callback, &ScenarioTestCallback::LockGranted2))
- .WillOnce(Invoke(&callback, &ScenarioTestCallback::LockGranted3));
-
- // OnSelectionChange will be called once after LockGranted3().
- EXPECT_CALL(*sink_, OnSelectionChange())
- .WillOnce(Return(S_OK));
-
- // OnLayoutChange will be called once after LockGranted3().
- EXPECT_CALL(*sink_, OnLayoutChange(_, _))
- .WillOnce(Return(S_OK));
-
- // OnTextChange will be called once after LockGranted3().
- EXPECT_CALL(*sink_, OnTextChange(_, _))
- .WillOnce(Return(S_OK));
-
- HRESULT result = kInvalidResult;
- EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
- EXPECT_EQ(S_OK, result);
- result = kInvalidResult;
- EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
- EXPECT_EQ(S_OK, result);
- result = kInvalidResult;
- EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
- EXPECT_EQ(S_OK, result);
-}
-
-class GetTextExtTestCallback : public TSFTextStoreTestCallback {
- public:
- explicit GetTextExtTestCallback(TSFTextStore* text_store)
- : TSFTextStoreTestCallback(text_store),
- layout_prepared_character_num_(0) {}
-
- HRESULT LockGranted(DWORD flags) {
- SetInternalState(L"0123456789012", 0, 0, 0);
- layout_prepared_character_num_ = 13;
-
- TsViewCookie view_cookie = 0;
- EXPECT_EQ(S_OK, text_store_->GetActiveView(&view_cookie));
- GetTextExtTest(view_cookie, 0, 0, 11, 12, 11, 20);
- GetTextExtTest(view_cookie, 0, 1, 11, 12, 20, 20);
- GetTextExtTest(view_cookie, 0, 2, 11, 12, 30, 20);
- GetTextExtTest(view_cookie, 9, 9, 100, 12, 100, 20);
- GetTextExtTest(view_cookie, 9, 10, 101, 12, 110, 20);
- GetTextExtTest(view_cookie, 10, 10, 110, 12, 110, 20);
- GetTextExtTest(view_cookie, 11, 11, 20, 112, 20, 120);
- GetTextExtTest(view_cookie, 11, 12, 21, 112, 30, 120);
- GetTextExtTest(view_cookie, 9, 12, 101, 12, 30, 120);
- GetTextExtTest(view_cookie, 9, 13, 101, 12, 40, 120);
- GetTextExtTest(view_cookie, 0, 13, 11, 12, 40, 120);
- GetTextExtTest(view_cookie, 13, 13, 40, 112, 40, 120);
-
- layout_prepared_character_num_ = 12;
- GetTextExtNoLayoutTest(view_cookie, 13, 13);
-
- layout_prepared_character_num_ = 0;
- GetTextExtNoLayoutTest(view_cookie, 0, 0);
-
- SetInternalState(L"", 0, 0, 0);
- GetTextExtTest(view_cookie, 0, 0, 1, 2, 4, 6);
-
- // Last character is not availabe due to timing issue of async API.
- // In this case, we will get first character bounds instead of whole text
- // bounds.
- SetInternalState(L"abc", 0, 0, 3);
- layout_prepared_character_num_ = 2;
- GetTextExtTest(view_cookie, 0, 0, 11, 12, 11, 20);
-
- // TODO(nona, kinaba): Remove following test case after PPAPI supporting
- // GetCompositionCharacterBounds.
- SetInternalState(L"a", 0, 0, 1);
- layout_prepared_character_num_ = 0;
- GetTextExtTest(view_cookie, 0, 1, 1, 2, 4, 6);
- return S_OK;
- }
-
- bool GetCompositionCharacterBounds(uint32 index, gfx::Rect* rect) {
- if (index >= layout_prepared_character_num_)
- return false;
- rect->set_x((index % 10) * 10 + 11);
- rect->set_y((index / 10) * 100 + 12);
- rect->set_width(9);
- rect->set_height(8);
- return true;
- }
-
- gfx::Rect GetCaretBounds() {
- return gfx::Rect(1, 2, 3, 4);
- }
-
- private:
- uint32 layout_prepared_character_num_;
-
- DISALLOW_COPY_AND_ASSIGN(GetTextExtTestCallback);
-};
-
-TEST_F(TSFTextStoreTest, GetTextExtTest) {
- GetTextExtTestCallback callback(text_store_);
- EXPECT_CALL(text_input_client_, GetCaretBounds())
- .WillRepeatedly(Invoke(&callback,
- &GetTextExtTestCallback::GetCaretBounds));
-
- EXPECT_CALL(text_input_client_, GetCompositionCharacterBounds(_, _))
- .WillRepeatedly(
- Invoke(&callback,
- &GetTextExtTestCallback::GetCompositionCharacterBounds));
-
- EXPECT_CALL(*sink_, OnLockGranted(_))
- .WillOnce(Invoke(&callback, &GetTextExtTestCallback::LockGranted));
-
- HRESULT result = kInvalidResult;
- EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ, &result));
- EXPECT_EQ(S_OK, result);
-}
-
-TEST_F(TSFTextStoreTest, RequestSupportedAttrs) {
- EXPECT_CALL(text_input_client_, GetTextInputType())
- .WillRepeatedly(Return(TEXT_INPUT_TYPE_TEXT));
- EXPECT_CALL(text_input_client_, GetTextInputMode())
- .WillRepeatedly(Return(TEXT_INPUT_MODE_DEFAULT));
-
- EXPECT_HRESULT_FAILED(text_store_->RequestSupportedAttrs(0, 1, NULL));
-
- const TS_ATTRID kUnknownAttributes[] = {GUID_NULL};
- EXPECT_HRESULT_FAILED(text_store_->RequestSupportedAttrs(
- 0, arraysize(kUnknownAttributes), kUnknownAttributes))
- << "Must fail for unknown attributes";
-
- const TS_ATTRID kAttributes[] = {GUID_NULL, GUID_PROP_INPUTSCOPE, GUID_NULL};
- EXPECT_EQ(S_OK, text_store_->RequestSupportedAttrs(
- 0, arraysize(kAttributes), kAttributes))
- << "InputScope must be supported";
-
- {
- SCOPED_TRACE("Check if RequestSupportedAttrs fails while focus is lost");
- // Emulate focus lost
- text_store_->SetFocusedTextInputClient(NULL, NULL);
- EXPECT_HRESULT_FAILED(text_store_->RequestSupportedAttrs(0, 0, NULL));
- EXPECT_HRESULT_FAILED(text_store_->RequestSupportedAttrs(
- 0, arraysize(kAttributes), kAttributes));
- }
-}
-
-TEST_F(TSFTextStoreTest, RetrieveRequestedAttrs) {
- EXPECT_CALL(text_input_client_, GetTextInputType())
- .WillRepeatedly(Return(TEXT_INPUT_TYPE_TEXT));
- EXPECT_CALL(text_input_client_, GetTextInputMode())
- .WillRepeatedly(Return(TEXT_INPUT_MODE_DEFAULT));
-
- ULONG num_copied = 0xfffffff;
- EXPECT_HRESULT_FAILED(text_store_->RetrieveRequestedAttrs(
- 1, NULL, &num_copied));
-
- {
- SCOPED_TRACE("Make sure if InputScope is supported");
- TS_ATTRVAL buffer[2] = {};
- num_copied = 0xfffffff;
- ASSERT_EQ(S_OK, text_store_->RetrieveRequestedAttrs(
- arraysize(buffer), buffer, &num_copied));
- bool input_scope_found = false;
- for (size_t i = 0; i < num_copied; ++i) {
- base::win::ScopedVariant variant;
- // Move ownership from |buffer[i].varValue| to |variant|.
- std::swap(*variant.Receive(), buffer[i].varValue);
- if (IsEqualGUID(buffer[i].idAttr, GUID_PROP_INPUTSCOPE)) {
- EXPECT_EQ(VT_UNKNOWN, variant.type());
- base::win::ScopedComPtr<ITfInputScope> input_scope;
- EXPECT_HRESULT_SUCCEEDED(input_scope.QueryFrom((&variant)->punkVal));
- input_scope_found = true;
- // we do not break here to clean up all the retrieved VARIANTs.
- }
- }
- EXPECT_TRUE(input_scope_found);
- }
- {
- SCOPED_TRACE("Check if RetrieveRequestedAttrs fails while focus is lost");
- // Emulate focus lost
- text_store_->SetFocusedTextInputClient(NULL, NULL);
- num_copied = 0xfffffff;
- TS_ATTRVAL buffer[2] = {};
- EXPECT_HRESULT_FAILED(text_store_->RetrieveRequestedAttrs(
- arraysize(buffer), buffer, &num_copied));
- }
-}
-
-} // namespace
-} // namespace ui