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 |
index bf2820323ef297a99dade58ca8ae4dad0a478ab1..f5117391ff719b58878b64447bb37c0f25ab8de5 100644 |
--- a/ui/base/ime/win/tsf_bridge.cc |
+++ b/ui/base/ime/win/tsf_bridge.cc |
@@ -6,9 +6,11 @@ |
#include <map> |
+#include "base/bind.h" |
#include "base/logging.h" |
#include "base/memory/ref_counted.h" |
#include "base/memory/scoped_ptr.h" |
+#include "base/memory/weak_ptr.h" |
#include "base/message_loop/message_loop.h" |
#include "base/threading/thread_local_storage.h" |
#include "base/win/scoped_comptr.h" |
@@ -28,7 +30,8 @@ base::ThreadLocalStorage::StaticSlot tls_tsf_bridge = TLS_INITIALIZER; |
// TsfBridgeDelegate ----------------------------------------------------------- |
// A TLS implementation of TSFBridge. |
-class TSFBridgeDelegate : public TSFBridge { |
+class TSFBridgeDelegate : public TSFBridge, |
+ public base::SupportsWeakPtr<TSFBridgeDelegate> { |
public: |
TSFBridgeDelegate(); |
virtual ~TSFBridgeDelegate(); |
@@ -46,6 +49,13 @@ class TSFBridgeDelegate : public TSFBridge { |
virtual base::win::ScopedComPtr<ITfThreadMgr> GetThreadManager() OVERRIDE; |
virtual TextInputClient* GetFocusedTextInputClient() const OVERRIDE; |
+ // See also *Callback functions below. To avoid reentrancy issue that |
+ // TextInputClient manipulates IME state during even handling, these methods |
+ // defer sending actual signals to renderer. |
+ virtual void OnCandidateWindowShown() OVERRIDE; |
+ virtual void OnCandidateWindowUpdated() OVERRIDE; |
+ virtual void OnCandidateWindowHidden() OVERRIDE; |
+ |
private: |
// Returns true if |tsf_document_map_| is successfully initialized. This |
// method should be called from and only from Initialize(). |
@@ -90,6 +100,12 @@ class TSFBridgeDelegate : public TSFBridge { |
void UpdateAssociateFocus(); |
void ClearAssociateFocus(); |
+ // Deferred callbacks for signalling TextInputClient about candidate window |
+ // appearance changes. |
+ void CandidateWindowShownCallback(); |
+ void CandidateWindowUpdatedCallback(); |
+ void CandidateWindowHiddenCallback(); |
+ |
// 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. |
@@ -484,6 +500,45 @@ TSFBridgeDelegate::TSFDocument* TSFBridgeDelegate::GetAssociatedDocument() { |
return &it->second; |
} |
+void TSFBridgeDelegate::OnCandidateWindowShown() { |
+ base::MessageLoop::current()->PostTask( |
+ FROM_HERE, |
+ base::Bind(&TSFBridgeDelegate::CandidateWindowShownCallback, |
+ AsWeakPtr())); |
+} |
+ |
+void TSFBridgeDelegate::OnCandidateWindowUpdated() { |
+ base::MessageLoop::current()->PostTask( |
+ FROM_HERE, |
+ base::Bind(&TSFBridgeDelegate::CandidateWindowUpdatedCallback, |
+ AsWeakPtr())); |
+} |
+ |
+void TSFBridgeDelegate::OnCandidateWindowHidden() { |
+ base::MessageLoop::current()->PostTask( |
+ FROM_HERE, |
+ base::Bind(&TSFBridgeDelegate::CandidateWindowHiddenCallback, |
+ AsWeakPtr())); |
+} |
+ |
+void TSFBridgeDelegate::CandidateWindowShownCallback() { |
+ TextInputClient* client = GetFocusedTextInputClient(); |
+ if (client) |
+ client->OnCandidateWindowShown(); |
+} |
+ |
+void TSFBridgeDelegate::CandidateWindowUpdatedCallback() { |
+ TextInputClient* client = GetFocusedTextInputClient(); |
+ if (client) |
+ client->OnCandidateWindowUpdated(); |
+} |
+ |
+void TSFBridgeDelegate::CandidateWindowHiddenCallback() { |
+ TextInputClient* client = GetFocusedTextInputClient(); |
+ if (client) |
+ client->OnCandidateWindowHidden(); |
+} |
+ |
} // namespace |