Index: ui/views/ime/input_method_bridge.cc |
diff --git a/ui/views/ime/input_method_bridge.cc b/ui/views/ime/input_method_bridge.cc |
index 5238313031e9dbb703c69df4408f611b050f4126..ea13bd481707e2f7cb6569ebf31c128ed8ab4a1d 100644 |
--- a/ui/views/ime/input_method_bridge.cc |
+++ b/ui/views/ime/input_method_bridge.cc |
@@ -5,6 +5,7 @@ |
#include "ui/views/ime/input_method_bridge.h" |
#include "ui/base/ime/input_method.h" |
+#include "ui/base/ime/input_method_observer.h" |
#include "ui/events/event.h" |
#include "ui/gfx/rect.h" |
#include "ui/views/view.h" |
@@ -12,6 +13,55 @@ |
namespace views { |
+// InputMethodBridge::HostObserver class --------------------------------------- |
+ |
+// An observer class for observing the host input method. When the host input |
+// method is destroyed, it will null out the |host_| field on the |
+// InputMethodBridge object. |
+class InputMethodBridge::HostObserver : public ui::InputMethodObserver { |
+ public: |
+ explicit HostObserver(InputMethodBridge* bridge); |
+ virtual ~HostObserver(); |
+ |
+ virtual void OnTextInputTypeChanged( |
+ const ui::TextInputClient* client) OVERRIDE {} |
+ virtual void OnFocus() OVERRIDE {} |
+ virtual void OnBlur() OVERRIDE {} |
+ virtual void OnUntranslatedIMEMessage( |
+ const base::NativeEvent& event) OVERRIDE {} |
+ virtual void OnCaretBoundsChanged( |
+ const ui::TextInputClient* client) OVERRIDE {} |
+ virtual void OnInputLocaleChanged() OVERRIDE {} |
+ virtual void OnTextInputStateChanged( |
+ const ui::TextInputClient* client) OVERRIDE {} |
+ virtual void OnInputMethodDestroyed( |
+ const ui::InputMethod* input_method) OVERRIDE; |
+ |
+ private: |
+ InputMethodBridge* bridge_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(HostObserver); |
+}; |
+ |
+InputMethodBridge::HostObserver::HostObserver(InputMethodBridge* bridge) |
+ : bridge_(bridge) { |
+ bridge_->host_->AddObserver(this); |
+} |
+ |
+InputMethodBridge::HostObserver::~HostObserver() { |
+ if (bridge_->host_) |
+ bridge_->host_->RemoveObserver(this); |
+} |
+ |
+void InputMethodBridge::HostObserver::OnInputMethodDestroyed( |
+ const ui::InputMethod* input_method) { |
+ DCHECK_EQ(bridge_->host_, input_method); |
+ bridge_->host_->RemoveObserver(this); |
+ bridge_->host_ = NULL; |
+} |
+ |
+// InputMethodBridge class ----------------------------------------------------- |
+ |
InputMethodBridge::InputMethodBridge(internal::InputMethodDelegate* delegate, |
ui::InputMethod* host, |
bool shared_input_method) |
@@ -19,6 +69,8 @@ InputMethodBridge::InputMethodBridge(internal::InputMethodDelegate* delegate, |
shared_input_method_(shared_input_method) { |
DCHECK(host_); |
SetDelegate(delegate); |
+ |
+ host_observer_.reset(new HostObserver(this)); |
} |
InputMethodBridge::~InputMethodBridge() { |
@@ -28,10 +80,15 @@ InputMethodBridge::~InputMethodBridge() { |
// this and go into |widget_|. NULL out |widget_| so we don't attempt to use |
// it. |
DetachFromWidget(); |
- host_->DetachTextInputClient(this); |
+ |
+ // Host input method might have been destroyed at this point. |
+ if (host_) |
+ host_->DetachTextInputClient(this); |
} |
void InputMethodBridge::OnFocus() { |
+ DCHECK(host_); |
+ |
// Direct the shared IME to send TextInputClient messages to |this| object. |
if (shared_input_method_ || !host_->GetTextInputClient()) |
host_->SetFocusedTextInputClient(this); |
@@ -43,6 +100,8 @@ void InputMethodBridge::OnFocus() { |
} |
void InputMethodBridge::OnBlur() { |
+ DCHECK(host_); |
+ |
if (HasCompositionText()) { |
ConfirmCompositionText(); |
host_->CancelComposition(this); |
@@ -54,6 +113,8 @@ void InputMethodBridge::OnBlur() { |
bool InputMethodBridge::OnUntranslatedIMEMessage(const base::NativeEvent& event, |
NativeEventResult* result) { |
+ DCHECK(host_); |
+ |
return host_->OnUntranslatedIMEMessage(event, result); |
} |
@@ -66,38 +127,54 @@ void InputMethodBridge::DispatchKeyEvent(const ui::KeyEvent& key) { |
} |
void InputMethodBridge::OnTextInputTypeChanged(View* view) { |
+ DCHECK(host_); |
+ |
if (IsViewFocused(view)) |
host_->OnTextInputTypeChanged(this); |
InputMethodBase::OnTextInputTypeChanged(view); |
} |
void InputMethodBridge::OnCaretBoundsChanged(View* view) { |
+ DCHECK(host_); |
+ |
if (IsViewFocused(view) && !IsTextInputTypeNone()) |
host_->OnCaretBoundsChanged(this); |
} |
void InputMethodBridge::CancelComposition(View* view) { |
+ DCHECK(host_); |
+ |
if (IsViewFocused(view)) |
host_->CancelComposition(this); |
} |
void InputMethodBridge::OnInputLocaleChanged() { |
- return host_->OnInputLocaleChanged(); |
+ DCHECK(host_); |
+ |
+ host_->OnInputLocaleChanged(); |
} |
std::string InputMethodBridge::GetInputLocale() { |
+ DCHECK(host_); |
+ |
return host_->GetInputLocale(); |
} |
base::i18n::TextDirection InputMethodBridge::GetInputTextDirection() { |
+ DCHECK(host_); |
+ |
return host_->GetInputTextDirection(); |
} |
bool InputMethodBridge::IsActive() { |
+ DCHECK(host_); |
+ |
return host_->IsActive(); |
} |
bool InputMethodBridge::IsCandidatePopupOpen() const { |
+ DCHECK(host_); |
+ |
return host_->IsCandidatePopupOpen(); |
} |