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

Unified Diff: ui/base/ime/win/tsf_bridge.cc

Issue 149073009: Remove InputMethodTSF, TSFEventRouter, TSFTextStore, TSFBridge (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: revert input_method_imm32 changes Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ui/base/ime/win/tsf_bridge.h ('k') | ui/base/ime/win/tsf_event_router.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/base/ime/win/tsf_bridge.cc
diff --git a/ui/base/ime/win/tsf_bridge.cc b/ui/base/ime/win/tsf_bridge.cc
deleted file mode 100644
index efbc285d2c461a044b1a2e4b1847918d4056e08e..0000000000000000000000000000000000000000
--- a/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(base::MessageLoopForUI::IsCurrent());
- 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(base::MessageLoopForUI::IsCurrent());
- 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(base::MessageLoopForUI::IsCurrent());
- 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(base::MessageLoopForUI::IsCurrent());
- DCHECK(IsInitialized());
-
- TSFDocument* document = GetAssociatedDocument();
- if (!document)
- return false;
- if (!document->text_store)
- return false;
-
- return document->text_store->CancelComposition();
-}
-
-bool TSFBridgeDelegate::ConfirmComposition() {
- DCHECK(base::MessageLoopForUI::IsCurrent());
- 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(base::MessageLoopForUI::IsCurrent());
- 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(base::MessageLoopForUI::IsCurrent());
- 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(base::MessageLoopForUI::IsCurrent());
- 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::MessageLoopForUI::IsCurrent()) {
- 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::MessageLoopForUI::IsCurrent()) {
- 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::MessageLoopForUI::IsCurrent()) {
- 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::MessageLoopForUI::IsCurrent()) {
- 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
« no previous file with comments | « ui/base/ime/win/tsf_bridge.h ('k') | ui/base/ime/win/tsf_event_router.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698