diff options
author | yukawa@chromium.org <yukawa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-10-29 13:42:47 +0000 |
---|---|---|
committer | yukawa@chromium.org <yukawa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-10-29 13:42:47 +0000 |
commit | 364fb6e517fc4fbc8196a4afba4f77b3d5300c3e (patch) | |
tree | 5ef6314eb44689e8803e9e6d52dbd040cd26a2d6 | |
parent | 61346e7350d8efd4589c735a75ed962a3f4bcb51 (diff) | |
download | chromium_src-364fb6e517fc4fbc8196a4afba4f77b3d5300c3e.zip chromium_src-364fb6e517fc4fbc8196a4afba4f77b3d5300c3e.tar.gz chromium_src-364fb6e517fc4fbc8196a4afba4f77b3d5300c3e.tar.bz2 |
Add InputMethodObserver support into InputMethodBase
This is a preparation CL to fix issue 164964.
Following observer callbacks are defined but not yet
supported by ui::InputMethodBase and its sub classes.
- InputMethodObserver::OnCaretBoundsChanged
- InputMethodObserver::OnInputLocaleChanged
This CL makes these callbacks functional for each
sub class of ui::InputMethodBase.
BUG=164964
TEST=ui_unittests --gtest_filter=InputMethodBaseTest.*
Review URL: https://codereview.chromium.org/48393003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@231563 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | ui/base/ime/input_method_base.cc | 14 | ||||
-rw-r--r-- | ui/base/ime/input_method_base.h | 2 | ||||
-rw-r--r-- | ui/base/ime/input_method_base_unittest.cc | 163 | ||||
-rw-r--r-- | ui/base/ime/input_method_ibus.cc | 120 | ||||
-rw-r--r-- | ui/base/ime/input_method_ibus.h | 4 | ||||
-rw-r--r-- | ui/base/ime/input_method_imm32.cc | 35 | ||||
-rw-r--r-- | ui/base/ime/input_method_linux_x11.cc | 14 | ||||
-rw-r--r-- | ui/base/ime/input_method_tsf.cc | 1 | ||||
-rw-r--r-- | ui/base/ime/input_method_win.cc | 1 |
9 files changed, 243 insertions, 111 deletions
diff --git a/ui/base/ime/input_method_base.cc b/ui/base/ime/input_method_base.cc index f211198..302b54d 100644 --- a/ui/base/ime/input_method_base.cc +++ b/ui/base/ime/input_method_base.cc @@ -74,6 +74,20 @@ void InputMethodBase::OnTextInputTypeChanged(const TextInputClient* client) { NotifyTextInputStateChanged(client); } +void InputMethodBase::OnCaretBoundsChanged(const TextInputClient* client) { + if (!IsTextInputClientFocused(client)) + return; + FOR_EACH_OBSERVER(InputMethodObserver, + observer_list_, + OnCaretBoundsChanged(client)); +} + +void InputMethodBase::OnInputLocaleChanged() { + FOR_EACH_OBSERVER(InputMethodObserver, + observer_list_, + OnInputLocaleChanged()); +} + TextInputType InputMethodBase::GetTextInputType() const { TextInputClient* client = GetTextInputClient(); return client ? client->GetTextInputType() : TEXT_INPUT_TYPE_NONE; diff --git a/ui/base/ime/input_method_base.h b/ui/base/ime/input_method_base.h index 665070a..07104f9 100644 --- a/ui/base/ime/input_method_base.h +++ b/ui/base/ime/input_method_base.h @@ -45,6 +45,8 @@ class UI_EXPORT InputMethodBase : NON_EXPORTED_BASE(public InputMethod) { // If a derived class overrides this method, it should call parent's // implementation. virtual void OnTextInputTypeChanged(const TextInputClient* client) OVERRIDE; + virtual void OnCaretBoundsChanged(const TextInputClient* client) OVERRIDE; + virtual void OnInputLocaleChanged() OVERRIDE; virtual TextInputType GetTextInputType() const OVERRIDE; virtual TextInputMode GetTextInputMode() const OVERRIDE; diff --git a/ui/base/ime/input_method_base_unittest.cc b/ui/base/ime/input_method_base_unittest.cc index 5d4447f..48623dd 100644 --- a/ui/base/ime/input_method_base_unittest.cc +++ b/ui/base/ime/input_method_base_unittest.cc @@ -110,13 +110,11 @@ class ClientChangeVerifier { DISALLOW_COPY_AND_ASSIGN(ClientChangeVerifier); }; -class MockInputMethodBase : public InputMethodBase { +class SimpleMockInputMethodBase : public InputMethodBase { public: - // Note: this class does not take the ownership of |verifier|. - explicit MockInputMethodBase(ClientChangeVerifier* verifier) - : verifier_(verifier) { + SimpleMockInputMethodBase() { } - virtual ~MockInputMethodBase() { + virtual ~SimpleMockInputMethodBase() { } private: @@ -132,13 +130,9 @@ class MockInputMethodBase : public InputMethodBase { virtual bool DispatchFabricatedKeyEvent(const ui::KeyEvent&) OVERRIDE { return false; } - virtual void OnCaretBoundsChanged(const TextInputClient* clien) OVERRIDE { - } - virtual void CancelComposition(const TextInputClient* clien) OVERRIDE { + virtual void CancelComposition(const TextInputClient* client) OVERRIDE { } - virtual void OnInputLocaleChanged() OVERRIDE { - } - virtual std::string GetInputLocale() OVERRIDE { + virtual std::string GetInputLocale() OVERRIDE{ return ""; } virtual base::i18n::TextDirection GetInputTextDirection() OVERRIDE { @@ -150,7 +144,19 @@ class MockInputMethodBase : public InputMethodBase { virtual bool IsCandidatePopupOpen() const OVERRIDE { return false; } + DISALLOW_COPY_AND_ASSIGN(SimpleMockInputMethodBase); +}; + +class MockInputMethodBase : public SimpleMockInputMethodBase { + public: + // Note: this class does not take the ownership of |verifier|. + explicit MockInputMethodBase(ClientChangeVerifier* verifier) + : verifier_(verifier) { + } + virtual ~MockInputMethodBase() { + } + private: // Overriden from InputMethodBase. virtual void OnWillChangeFocusedClient(TextInputClient* focused_before, TextInputClient* focused) OVERRIDE { @@ -166,33 +172,65 @@ class MockInputMethodBase : public InputMethodBase { DISALLOW_COPY_AND_ASSIGN(MockInputMethodBase); }; -class MockInputMethodObserver : public InputMethodObserver { +class SimpleMockInputMethodObserver : public InputMethodObserver { public: - // Note: this class does not take the ownership of |verifier|. - explicit MockInputMethodObserver(ClientChangeVerifier* verifier) - : verifier_(verifier) { + SimpleMockInputMethodObserver() + : on_caret_bounds_changed_(0), + on_input_locale_changed_(0) { } - virtual ~MockInputMethodObserver() { + virtual ~SimpleMockInputMethodObserver() { + } + void Reset() { + on_caret_bounds_changed_ = 0; + on_input_locale_changed_ = 0; + } + size_t on_caret_bounds_changed() const { + return on_caret_bounds_changed_; + } + size_t on_input_locale_changed() const { + return on_input_locale_changed_; } private: - virtual void OnTextInputTypeChanged(const TextInputClient* client) OVERRIDE { + // Overriden from InputMethodObserver. + virtual void OnTextInputTypeChanged(const TextInputClient* client) OVERRIDE{ } - virtual void OnFocus() OVERRIDE { + virtual void OnFocus() OVERRIDE{ } - virtual void OnBlur() OVERRIDE { + virtual void OnBlur() OVERRIDE{ } virtual void OnUntranslatedIMEMessage( - const base::NativeEvent& event) OVERRIDE { + const base::NativeEvent& event) OVERRIDE{ } - virtual void OnCaretBoundsChanged(const TextInputClient* client) OVERRIDE { + virtual void OnCaretBoundsChanged(const TextInputClient* client) OVERRIDE{ + ++on_caret_bounds_changed_; } - virtual void OnInputLocaleChanged() OVERRIDE { + virtual void OnInputLocaleChanged() OVERRIDE{ + ++on_input_locale_changed_; } - virtual void OnTextInputStateChanged(const TextInputClient* client) OVERRIDE { - verifier_->OnTextInputStateChanged(client); + virtual void OnTextInputStateChanged(const TextInputClient* client) OVERRIDE{ } - virtual void OnInputMethodDestroyed(const InputMethod* client) OVERRIDE { + virtual void OnInputMethodDestroyed(const InputMethod* client) OVERRIDE{ + } + + size_t on_caret_bounds_changed_; + size_t on_input_locale_changed_; + DISALLOW_COPY_AND_ASSIGN(SimpleMockInputMethodObserver); +}; + +class MockInputMethodObserver : public SimpleMockInputMethodObserver { + public: + // Note: this class does not take the ownership of |verifier|. + explicit MockInputMethodObserver(ClientChangeVerifier* verifier) + : verifier_(verifier) { + } + virtual ~MockInputMethodObserver() { + } + + private: + // Overriden from SimpleMockInputMethodObserver. + virtual void OnTextInputStateChanged(const TextInputClient* client) OVERRIDE{ + verifier_->OnTextInputStateChanged(client); } ClientChangeVerifier* verifier_; @@ -379,5 +417,80 @@ TEST(InputMethodBaseTest, SetStickyFocusedTextInputClient) { } } +TEST(InputMethodBaseTest, OnCaretBoundsChanged) { + DummyTextInputClient text_input_client; + DummyTextInputClient text_input_client_the_other; + + SimpleMockInputMethodBase input_method; + SimpleMockInputMethodObserver input_method_observer; + InputMethodScopedObserver scoped_observer(&input_method_observer); + scoped_observer.Add(&input_method); + + // Assume that the top-level-widget gains focus. + input_method.OnFocus(); + + { + SCOPED_TRACE("OnCaretBoundsChanged callback must not be fired when no text " + "input client is focused"); + ASSERT_EQ(NULL, input_method.GetTextInputClient()); + + input_method_observer.Reset(); + input_method.OnCaretBoundsChanged(&text_input_client); + EXPECT_EQ(0u, input_method_observer.on_caret_bounds_changed()); + input_method.OnCaretBoundsChanged(NULL); + EXPECT_EQ(0u, input_method_observer.on_caret_bounds_changed()); + } + + { + SCOPED_TRACE("OnCaretBoundsChanged callback must be fired when and only " + "the event is notified from the focused text input client"); + + input_method.SetFocusedTextInputClient(&text_input_client); + ASSERT_EQ(&text_input_client, input_method.GetTextInputClient()); + + // Must fire the event + input_method_observer.Reset(); + input_method.OnCaretBoundsChanged(&text_input_client); + EXPECT_EQ(1u, input_method_observer.on_caret_bounds_changed()); + + // Must not fire the event + input_method_observer.Reset(); + input_method.OnCaretBoundsChanged(NULL); + EXPECT_EQ(0u, input_method_observer.on_caret_bounds_changed()); + + // Must not fire the event + input_method_observer.Reset(); + input_method.OnCaretBoundsChanged(&text_input_client_the_other); + EXPECT_EQ(0u, input_method_observer.on_caret_bounds_changed()); + } +} + +TEST(InputMethodBaseTest, OnInputLocaleChanged) { + DummyTextInputClient text_input_client; + + SimpleMockInputMethodBase input_method; + SimpleMockInputMethodObserver input_method_observer; + InputMethodScopedObserver scoped_observer(&input_method_observer); + scoped_observer.Add(&input_method); + + // Assume that the top-level-widget gains focus. + input_method.OnFocus(); + + { + SCOPED_TRACE("OnInputLocaleChanged callback can be fired even when no text " + "input client is focused"); + ASSERT_EQ(NULL, input_method.GetTextInputClient()); + + input_method_observer.Reset(); + input_method.OnInputLocaleChanged(); + EXPECT_EQ(1u, input_method_observer.on_input_locale_changed()); + + input_method.SetFocusedTextInputClient(&text_input_client); + input_method_observer.Reset(); + input_method.OnInputLocaleChanged(); + EXPECT_EQ(1u, input_method_observer.on_input_locale_changed()); + } +} + } // namespace } // namespace ui diff --git a/ui/base/ime/input_method_ibus.cc b/ui/base/ime/input_method_ibus.cc index d712463..c0bfed1 100644 --- a/ui/base/ime/input_method_ibus.cc +++ b/ui/base/ime/input_method_ibus.cc @@ -234,61 +234,8 @@ void InputMethodIBus::OnTextInputTypeChanged(const TextInputClient* client) { } void InputMethodIBus::OnCaretBoundsChanged(const TextInputClient* client) { - if (!context_focused_ || !IsTextInputClientFocused(client)) - return; - - // The current text input type should not be NONE if |context_| is focused. - DCHECK(!IsTextInputTypeNone()); - const gfx::Rect rect = GetTextInputClient()->GetCaretBounds(); - - gfx::Rect composition_head; - if (!GetTextInputClient()->GetCompositionCharacterBounds(0, - &composition_head)) { - composition_head = rect; - } - - chromeos::IBusPanelCandidateWindowHandlerInterface* candidate_window = - chromeos::IBusBridge::Get()->GetCandidateWindowHandler(); - if (!candidate_window) - return; - candidate_window->SetCursorLocation( - GfxRectToIBusRect(rect), - GfxRectToIBusRect(composition_head)); - - gfx::Range text_range; - gfx::Range selection_range; - string16 surrounding_text; - if (!GetTextInputClient()->GetTextRange(&text_range) || - !GetTextInputClient()->GetTextFromRange(text_range, &surrounding_text) || - !GetTextInputClient()->GetSelectionRange(&selection_range)) { - previous_surrounding_text_.clear(); - previous_selection_range_ = gfx::Range::InvalidRange(); - return; - } - - if (previous_selection_range_ == selection_range && - previous_surrounding_text_ == surrounding_text) - return; - - previous_selection_range_ = selection_range; - previous_surrounding_text_ = surrounding_text; - - if (!selection_range.IsValid()) { - // TODO(nona): Ideally selection_range should not be invalid. - // TODO(nona): If javascript changes the focus on page loading, even (0,0) - // can not be obtained. Need investigation. - return; - } - - // Here SetSurroundingText accepts relative position of |surrounding_text|, so - // we have to convert |selection_range| from node coordinates to - // |surrounding_text| coordinates. - if (!GetEngine()) - return; - GetEngine()->SetSurroundingText( - UTF16ToUTF8(surrounding_text), - selection_range.start() - text_range.start(), - selection_range.end() - text_range.start()); + OnCaretBoundsChangedInternal(client); + InputMethodBase::OnCaretBoundsChanged(client); } void InputMethodIBus::CancelComposition(const TextInputClient* client) { @@ -296,10 +243,6 @@ void InputMethodIBus::CancelComposition(const TextInputClient* client) { ResetContext(); } -void InputMethodIBus::OnInputLocaleChanged() { - // Not supported. -} - std::string InputMethodIBus::GetInputLocale() { // Not supported. return ""; @@ -806,4 +749,63 @@ void InputMethodIBus::ExtractCompositionText( } } +void InputMethodIBus::OnCaretBoundsChangedInternal( + const TextInputClient* client) { + if (!context_focused_ || !IsTextInputClientFocused(client)) + return; + + // The current text input type should not be NONE if |context_| is focused. + DCHECK(!IsTextInputTypeNone()); + const gfx::Rect rect = GetTextInputClient()->GetCaretBounds(); + + gfx::Rect composition_head; + if (!GetTextInputClient()->GetCompositionCharacterBounds(0, + &composition_head)) { + composition_head = rect; + } + + chromeos::IBusPanelCandidateWindowHandlerInterface* candidate_window = + chromeos::IBusBridge::Get()->GetCandidateWindowHandler(); + if (!candidate_window) + return; + candidate_window->SetCursorLocation( + GfxRectToIBusRect(rect), + GfxRectToIBusRect(composition_head)); + + gfx::Range text_range; + gfx::Range selection_range; + string16 surrounding_text; + if (!GetTextInputClient()->GetTextRange(&text_range) || + !GetTextInputClient()->GetTextFromRange(text_range, &surrounding_text) || + !GetTextInputClient()->GetSelectionRange(&selection_range)) { + previous_surrounding_text_.clear(); + previous_selection_range_ = gfx::Range::InvalidRange(); + return; + } + + if (previous_selection_range_ == selection_range && + previous_surrounding_text_ == surrounding_text) + return; + + previous_selection_range_ = selection_range; + previous_surrounding_text_ = surrounding_text; + + if (!selection_range.IsValid()) { + // TODO(nona): Ideally selection_range should not be invalid. + // TODO(nona): If javascript changes the focus on page loading, even (0,0) + // can not be obtained. Need investigation. + return; + } + + // Here SetSurroundingText accepts relative position of |surrounding_text|, so + // we have to convert |selection_range| from node coordinates to + // |surrounding_text| coordinates. + if (!GetEngine()) + return; + GetEngine()->SetSurroundingText( + UTF16ToUTF8(surrounding_text), + selection_range.start() - text_range.start(), + selection_range.end() - text_range.start()); +} + } // namespace ui diff --git a/ui/base/ime/input_method_ibus.h b/ui/base/ime/input_method_ibus.h index 1f0b194..b4aecde 100644 --- a/ui/base/ime/input_method_ibus.h +++ b/ui/base/ime/input_method_ibus.h @@ -47,7 +47,6 @@ class UI_EXPORT InputMethodIBus virtual void OnTextInputTypeChanged(const TextInputClient* client) OVERRIDE; virtual void OnCaretBoundsChanged(const TextInputClient* client) OVERRIDE; virtual void CancelComposition(const TextInputClient* client) OVERRIDE; - virtual void OnInputLocaleChanged() OVERRIDE; virtual std::string GetInputLocale() OVERRIDE; virtual base::i18n::TextDirection GetInputTextDirection() OVERRIDE; virtual bool IsActive() OVERRIDE; @@ -139,6 +138,9 @@ class UI_EXPORT InputMethodIBus uint32 ibus_keyval, uint32 ibus_keycode, uint32 ibus_state, bool is_handled); + // Processes a caret bounds changed event. + void OnCaretBoundsChangedInternal(const TextInputClient* client); + // All pending key events. Note: we do not own these object, we just save // pointers to these object so that we can abandon them when necessary. // They will be deleted in ProcessKeyEventDone(). diff --git a/ui/base/ime/input_method_imm32.cc b/ui/base/ime/input_method_imm32.cc index 4f17ea9..ca02fa3 100644 --- a/ui/base/ime/input_method_imm32.cc +++ b/ui/base/ime/input_method_imm32.cc @@ -94,26 +94,23 @@ void InputMethodIMM32::OnTextInputTypeChanged(const TextInputClient* client) { } void InputMethodIMM32::OnCaretBoundsChanged(const TextInputClient* client) { - if (!enabled_ || !IsTextInputClientFocused(client) || - !IsWindowFocused(client)) { - return; + if (enabled_ && IsTextInputClientFocused(client) && IsWindowFocused(client)) { + // The current text input type should not be NONE if |client| is focused. + DCHECK(!IsTextInputTypeNone()); + gfx::Rect screen_bounds(GetTextInputClient()->GetCaretBounds()); + + HWND attached_window = GetAttachedWindowHandle(client); + // TODO(ime): see comment in TextInputClient::GetCaretBounds(), this + // conversion shouldn't be necessary. + RECT r = {}; + GetClientRect(attached_window, &r); + POINT window_point = { screen_bounds.x(), screen_bounds.y() }; + ScreenToClient(attached_window, &window_point); + gfx::Rect caret_rect(gfx::Point(window_point.x, window_point.y), + screen_bounds.size()); + imm32_manager_.UpdateCaretRect(attached_window, caret_rect); } - - // The current text input type should not be NONE if |client| is focused. - DCHECK(!IsTextInputTypeNone()); - gfx::Rect screen_bounds(GetTextInputClient()->GetCaretBounds()); - - HWND attached_window = GetAttachedWindowHandle(client); - // TODO(ime): see comment in TextInputClient::GetCaretBounds(), this - // conversion shouldn't be necessary. - RECT r; - GetClientRect(attached_window, &r); - POINT window_point = { screen_bounds.x(), screen_bounds.y() }; - ScreenToClient(attached_window, &window_point); - imm32_manager_.UpdateCaretRect( - attached_window, - gfx::Rect(gfx::Point(window_point.x, window_point.y), - screen_bounds.size())); + InputMethodWin::OnCaretBoundsChanged(client); } void InputMethodIMM32::CancelComposition(const TextInputClient* client) { diff --git a/ui/base/ime/input_method_linux_x11.cc b/ui/base/ime/input_method_linux_x11.cc index 415a7bd..5973761 100644 --- a/ui/base/ime/input_method_linux_x11.cc +++ b/ui/base/ime/input_method_linux_x11.cc @@ -110,13 +110,12 @@ void InputMethodLinuxX11::OnTextInputTypeChanged( InputMethodBase::OnTextInputTypeChanged(client); } -void InputMethodLinuxX11::OnCaretBoundsChanged( - const TextInputClient* client) { - if (!IsTextInputClientFocused(client)) - return; - - input_method_context_->OnCaretBoundsChanged( - GetTextInputClient()->GetCaretBounds()); +void InputMethodLinuxX11::OnCaretBoundsChanged(const TextInputClient* client) { + if (IsTextInputClientFocused(client)) { + input_method_context_->OnCaretBoundsChanged( + GetTextInputClient()->GetCaretBounds()); + } + InputMethodBase::OnCaretBoundsChanged(client); } void InputMethodLinuxX11::CancelComposition(const TextInputClient* client) { @@ -128,6 +127,7 @@ void InputMethodLinuxX11::CancelComposition(const TextInputClient* client) { } void InputMethodLinuxX11::OnInputLocaleChanged() { + InputMethodBase::OnInputLocaleChanged(); } std::string InputMethodLinuxX11::GetInputLocale() { diff --git a/ui/base/ime/input_method_tsf.cc b/ui/base/ime/input_method_tsf.cc index aaec2e0..944f977 100644 --- a/ui/base/ime/input_method_tsf.cc +++ b/ui/base/ime/input_method_tsf.cc @@ -108,6 +108,7 @@ void InputMethodTSF::OnTextInputTypeChanged(const TextInputClient* client) { void InputMethodTSF::OnCaretBoundsChanged(const TextInputClient* client) { if (IsTextInputClientFocused(client) && IsWindowFocused(client)) ui::TSFBridge::GetInstance()->OnTextLayoutChanged(); + InputMethodWin::OnCaretBoundsChanged(client); } void InputMethodTSF::CancelComposition(const TextInputClient* client) { diff --git a/ui/base/ime/input_method_win.cc b/ui/base/ime/input_method_win.cc index 4bb8b6a..adefd889 100644 --- a/ui/base/ime/input_method_win.cc +++ b/ui/base/ime/input_method_win.cc @@ -94,6 +94,7 @@ void InputMethodWin::OnInputLocaleChanged() { locale_ = imm32_manager_.GetInputLanguageName(); direction_ = imm32_manager_.GetTextDirection(); OnInputMethodChanged(); + InputMethodBase::OnInputLocaleChanged(); } std::string InputMethodWin::GetInputLocale() { |