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

Side by Side Diff: ui/base/ime/win/tsf_bridge.cc

Issue 16648002: Enable TsfBridge to re-initialize (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Rebase Created 7 years, 6 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 unified diff | Download patch
« no previous file with comments | « ui/base/ime/win/tsf_bridge.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <msctf.h> 5 #include <msctf.h>
6 6
7 #include <map> 7 #include <map>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/memory/ref_counted.h" 10 #include "base/memory/ref_counted.h"
11 #include "base/memory/scoped_ptr.h" 11 #include "base/memory/scoped_ptr.h"
12 #include "base/memory/singleton.h"
13 #include "base/message_loop.h" 12 #include "base/message_loop.h"
14 #include "base/threading/thread_local_storage.h" 13 #include "base/threading/thread_local_storage.h"
15 #include "base/win/scoped_comptr.h" 14 #include "base/win/scoped_comptr.h"
16 #include "base/win/scoped_variant.h" 15 #include "base/win/scoped_variant.h"
17 #include "ui/base/ime/text_input_client.h" 16 #include "ui/base/ime/text_input_client.h"
18 #include "ui/base/ime/win/tsf_bridge.h" 17 #include "ui/base/ime/win/tsf_bridge.h"
19 #include "ui/base/ime/win/tsf_text_store.h" 18 #include "ui/base/ime/win/tsf_text_store.h"
20 19
21 namespace ui { 20 namespace ui {
22 21
23 namespace { 22 namespace {
24 23
25 // We use thread local storage for TSFBridge lifespan management. 24 // We use thread local storage for TSFBridge lifespan management.
26 base::ThreadLocalStorage::StaticSlot tls_tsf_bridge = TLS_INITIALIZER; 25 base::ThreadLocalStorage::StaticSlot tls_tsf_bridge = TLS_INITIALIZER;
27 26
28 27
29 // TsfBridgeDelegate ----------------------------------------------------------- 28 // TsfBridgeDelegate -----------------------------------------------------------
30 29
31 // A TLS implementation of TSFBridge. 30 // A TLS implementation of TSFBridge.
32 class TSFBridgeDelegate : public TSFBridge { 31 class TSFBridgeDelegate : public TSFBridge {
33 public: 32 public:
34 TSFBridgeDelegate(); 33 TSFBridgeDelegate();
35 virtual ~TSFBridgeDelegate(); 34 virtual ~TSFBridgeDelegate();
36 35
37 bool Initialize(); 36 bool Initialize();
38 37
39 // TsfBridge: 38 // TsfBridge:
40 virtual void Shutdown() OVERRIDE;
41 virtual void OnTextInputTypeChanged(TextInputClient* client) OVERRIDE; 39 virtual void OnTextInputTypeChanged(TextInputClient* client) OVERRIDE;
42 virtual void OnTextLayoutChanged() OVERRIDE; 40 virtual void OnTextLayoutChanged() OVERRIDE;
43 virtual bool CancelComposition() OVERRIDE; 41 virtual bool CancelComposition() OVERRIDE;
44 virtual void SetFocusedClient(HWND focused_window, 42 virtual void SetFocusedClient(HWND focused_window,
45 TextInputClient* client) OVERRIDE; 43 TextInputClient* client) OVERRIDE;
46 virtual void RemoveFocusedClient(TextInputClient* client) OVERRIDE; 44 virtual void RemoveFocusedClient(TextInputClient* client) OVERRIDE;
47 virtual base::win::ScopedComPtr<ITfThreadMgr> GetThreadManager() OVERRIDE; 45 virtual base::win::ScopedComPtr<ITfThreadMgr> GetThreadManager() OVERRIDE;
48 virtual TextInputClient* GetFocusedTextInputClient() const OVERRIDE; 46 virtual TextInputClient* GetFocusedTextInputClient() const OVERRIDE;
49 47
50 private: 48 private:
51 friend struct DefaultSingletonTraits<TSFBridgeDelegate>;
52
53 // Returns true if |tsf_document_map_| is successfully initialized. This 49 // Returns true if |tsf_document_map_| is successfully initialized. This
54 // method should be called from and only from Initialize(). 50 // method should be called from and only from Initialize().
55 bool InitializeDocumentMapInternal(); 51 bool InitializeDocumentMapInternal();
56 52
57 // Returns true if |context| is successfully updated to be a disabled 53 // Returns true if |context| is successfully updated to be a disabled
58 // context, where an IME should be deactivated. This is suitable for some 54 // context, where an IME should be deactivated. This is suitable for some
59 // special input context such as password fields. 55 // special input context such as password fields.
60 bool InitializeDisabledContext(ITfContext* context); 56 bool InitializeDisabledContext(ITfContext* context);
61 57
62 // Returns true if a TSF document manager and a TSF context is successfully 58 // Returns true if a TSF document manager and a TSF context is successfully
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
115 111
116 DISALLOW_COPY_AND_ASSIGN(TSFBridgeDelegate); 112 DISALLOW_COPY_AND_ASSIGN(TSFBridgeDelegate);
117 }; 113 };
118 114
119 TSFBridgeDelegate::TSFBridgeDelegate() 115 TSFBridgeDelegate::TSFBridgeDelegate()
120 : client_id_(TF_CLIENTID_NULL), 116 : client_id_(TF_CLIENTID_NULL),
121 client_(NULL) { 117 client_(NULL) {
122 } 118 }
123 119
124 TSFBridgeDelegate::~TSFBridgeDelegate() { 120 TSFBridgeDelegate::~TSFBridgeDelegate() {
121 DCHECK_EQ(base::MessageLoop::TYPE_UI, base::MessageLoop::current()->type());
122 if (!IsInitialized())
123 return;
124 for (TSFDocumentMap::iterator it = tsf_document_map_.begin();
125 it != tsf_document_map_.end(); ++it) {
126 base::win::ScopedComPtr<ITfContext> context;
127 base::win::ScopedComPtr<ITfSource> source;
128 if (it->second.cookie != TF_INVALID_COOKIE &&
129 SUCCEEDED(it->second.document_manager->GetBase(context.Receive())) &&
130 SUCCEEDED(source.QueryFrom(context))) {
131 source->UnadviseSink(it->second.cookie);
132 }
133 }
134 tsf_document_map_.clear();
135
136 client_id_ = TF_CLIENTID_NULL;
125 } 137 }
126 138
127 bool TSFBridgeDelegate::Initialize() { 139 bool TSFBridgeDelegate::Initialize() {
128 DCHECK_EQ(base::MessageLoop::TYPE_UI, base::MessageLoop::current()->type()); 140 DCHECK_EQ(base::MessageLoop::TYPE_UI, base::MessageLoop::current()->type());
129 if (client_id_ != TF_CLIENTID_NULL) { 141 if (client_id_ != TF_CLIENTID_NULL) {
130 DVLOG(1) << "Already initialized."; 142 DVLOG(1) << "Already initialized.";
131 return false; 143 return false;
132 } 144 }
133 145
134 if (FAILED(thread_manager_.CreateInstance(CLSID_TF_ThreadMgr))) { 146 if (FAILED(thread_manager_.CreateInstance(CLSID_TF_ThreadMgr))) {
(...skipping 30 matching lines...) Expand all
165 base::win::ScopedVariant sentence_variant; 177 base::win::ScopedVariant sentence_variant;
166 sentence_variant.Set(TF_SENTENCEMODE_PHRASEPREDICT); 178 sentence_variant.Set(TF_SENTENCEMODE_PHRASEPREDICT);
167 if (FAILED(sentence_compartment->SetValue(client_id_, &sentence_variant))) { 179 if (FAILED(sentence_compartment->SetValue(client_id_, &sentence_variant))) {
168 DVLOG(1) << "Failed to change the sentence mode."; 180 DVLOG(1) << "Failed to change the sentence mode.";
169 return false; 181 return false;
170 } 182 }
171 183
172 return true; 184 return true;
173 } 185 }
174 186
175 void TSFBridgeDelegate::Shutdown() {
176 DCHECK_EQ(base::MessageLoop::TYPE_UI, base::MessageLoop::current()->type());
177 if (!IsInitialized())
178 return;
179 for (TSFDocumentMap::iterator it = tsf_document_map_.begin();
180 it != tsf_document_map_.end(); ++it) {
181 base::win::ScopedComPtr<ITfContext> context;
182 base::win::ScopedComPtr<ITfSource> source;
183 if (it->second.cookie != TF_INVALID_COOKIE &&
184 SUCCEEDED(it->second.document_manager->GetBase(context.Receive())) &&
185 SUCCEEDED(source.QueryFrom(context))) {
186 source->UnadviseSink(it->second.cookie);
187 }
188 }
189 tsf_document_map_.clear();
190
191 client_id_ = TF_CLIENTID_NULL;
192 }
193
194 void TSFBridgeDelegate::OnTextInputTypeChanged(TextInputClient* client) { 187 void TSFBridgeDelegate::OnTextInputTypeChanged(TextInputClient* client) {
195 DCHECK_EQ(base::MessageLoop::TYPE_UI, base::MessageLoop::current()->type()); 188 DCHECK_EQ(base::MessageLoop::TYPE_UI, base::MessageLoop::current()->type());
196 DCHECK(IsInitialized()); 189 DCHECK(IsInitialized());
197 190
198 if (client != client_) { 191 if (client != client_) {
199 // Called from not focusing client. Do nothing. 192 // Called from not focusing client. Do nothing.
200 return; 193 return;
201 } 194 }
202 195
203 TSFDocument* document = GetAssociatedDocument(); 196 TSFDocument* document = GetAssociatedDocument();
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after
453 } 446 }
454 447
455 // static 448 // static
456 bool TSFBridge::Initialize() { 449 bool TSFBridge::Initialize() {
457 if (base::MessageLoop::current()->type() != base::MessageLoop::TYPE_UI) { 450 if (base::MessageLoop::current()->type() != base::MessageLoop::TYPE_UI) {
458 DVLOG(1) << "Do not use TSFBridge without UI thread."; 451 DVLOG(1) << "Do not use TSFBridge without UI thread.";
459 return false; 452 return false;
460 } 453 }
461 if (!tls_tsf_bridge.initialized()) { 454 if (!tls_tsf_bridge.initialized()) {
462 tls_tsf_bridge.Initialize(TSFBridge::Finalize); 455 tls_tsf_bridge.Initialize(TSFBridge::Finalize);
463 TSFBridgeDelegate* delegate = new TSFBridgeDelegate();
464 tls_tsf_bridge.Set(delegate);
465 return delegate->Initialize();
466 } 456 }
467 return true; 457 TSFBridgeDelegate* delegate =
458 static_cast<TSFBridgeDelegate*>(tls_tsf_bridge.Get());
459 if (delegate)
460 return true;
461 delegate = new TSFBridgeDelegate();
462 tls_tsf_bridge.Set(delegate);
463 return delegate->Initialize();
468 } 464 }
469 465
470 // static 466 // static
471 TSFBridge* TSFBridge::ReplaceForTesting(TSFBridge* bridge) { 467 TSFBridge* TSFBridge::ReplaceForTesting(TSFBridge* bridge) {
472 if (base::MessageLoop::current()->type() != base::MessageLoop::TYPE_UI) { 468 if (base::MessageLoop::current()->type() != base::MessageLoop::TYPE_UI) {
473 DVLOG(1) << "Do not use TSFBridge without UI thread."; 469 DVLOG(1) << "Do not use TSFBridge without UI thread.";
474 return NULL; 470 return NULL;
475 } 471 }
476 TSFBridge* old_bridge = TSFBridge::GetInstance(); 472 TSFBridge* old_bridge = TSFBridge::GetInstance();
477 tls_tsf_bridge.Set(bridge); 473 tls_tsf_bridge.Set(bridge);
478 return old_bridge; 474 return old_bridge;
479 } 475 }
480 476
481 // static 477 // static
478 void TSFBridge::Shutdown() {
479 if (base::MessageLoop::current()->type() != base::MessageLoop::TYPE_UI) {
480 DVLOG(1) << "Do not use TSFBridge without UI thread.";
481 }
482 if (tls_tsf_bridge.initialized()) {
483 TSFBridgeDelegate* delegate =
484 static_cast<TSFBridgeDelegate*>(tls_tsf_bridge.Get());
485 tls_tsf_bridge.Set(NULL);
486 delete delegate;
487 }
488 }
489
490 // static
482 TSFBridge* TSFBridge::GetInstance() { 491 TSFBridge* TSFBridge::GetInstance() {
483 if (base::MessageLoop::current()->type() != base::MessageLoop::TYPE_UI) { 492 if (base::MessageLoop::current()->type() != base::MessageLoop::TYPE_UI) {
484 DVLOG(1) << "Do not use TSFBridge without UI thread."; 493 DVLOG(1) << "Do not use TSFBridge without UI thread.";
485 return NULL; 494 return NULL;
486 } 495 }
487 TSFBridgeDelegate* delegate = 496 TSFBridgeDelegate* delegate =
488 static_cast<TSFBridgeDelegate*>(tls_tsf_bridge.Get()); 497 static_cast<TSFBridgeDelegate*>(tls_tsf_bridge.Get());
489 DCHECK(delegate) << "Do no call GetInstance before TSFBridge::Initialize."; 498 DCHECK(delegate) << "Do no call GetInstance before TSFBridge::Initialize.";
490 return delegate; 499 return delegate;
491 } 500 }
492 501
493 // static 502 // static
494 void TSFBridge::Finalize(void* data) { 503 void TSFBridge::Finalize(void* data) {
495 TSFBridgeDelegate* delegate = static_cast<TSFBridgeDelegate*>(data); 504 TSFBridgeDelegate* delegate = static_cast<TSFBridgeDelegate*>(data);
496 delete delegate; 505 delete delegate;
497 } 506 }
498 507
499 } // namespace ui 508 } // namespace ui
OLDNEW
« no previous file with comments | « ui/base/ime/win/tsf_bridge.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698