| Index: ui/base/ime/win/tsf_event_router.cc
|
| diff --git a/ui/base/ime/win/tsf_event_router.cc b/ui/base/ime/win/tsf_event_router.cc
|
| index 92e20f31ca5e53d3e0e7cdff3630e3685d1cc190..4cf625ecb16d3ce6d724e86fa430a82d8a949822 100644
|
| --- a/ui/base/ime/win/tsf_event_router.cc
|
| +++ b/ui/base/ime/win/tsf_event_router.cc
|
| @@ -11,6 +11,7 @@
|
| #include "base/bind.h"
|
| #include "base/win/scoped_comptr.h"
|
| #include "base/win/metro.h"
|
| +#include "ui/base/range/range.h"
|
| #include "ui/base/win/atl_module.h"
|
|
|
| namespace ui {
|
| @@ -56,8 +57,9 @@ class ATL_NO_VTABLE TsfEventRouter::TsfEventRouterDelegate
|
| void SetRouter(TsfEventRouter* router);
|
|
|
| private:
|
| - // Returns true if the given |context| is composing.
|
| - static bool IsImeComposingInternal(ITfContext* context);
|
| + // Returns current composition range. Returns ui::Range::InvalidRange if there
|
| + // is no composition.
|
| + static ui::Range GetCompositionRange(ITfContext* context);
|
|
|
| // Returns true if the given |element_id| represents the candidate window.
|
| bool IsCandidateWindowInternal(DWORD element_id);
|
| @@ -84,6 +86,7 @@ class ATL_NO_VTABLE TsfEventRouter::TsfEventRouterDelegate
|
| DWORD ui_source_cookie_;
|
|
|
| TsfEventRouter* router_;
|
| + ui::Range previous_composition_range_;
|
|
|
| DISALLOW_COPY_AND_ASSIGN(TsfEventRouterDelegate);
|
| };
|
| @@ -91,7 +94,8 @@ class ATL_NO_VTABLE TsfEventRouter::TsfEventRouterDelegate
|
| TsfEventRouter::TsfEventRouterDelegate::TsfEventRouterDelegate()
|
| : context_source_cookie_(TF_INVALID_COOKIE),
|
| ui_source_cookie_(TF_INVALID_COOKIE),
|
| - router_(NULL) {
|
| + router_(NULL),
|
| + previous_composition_range_(ui::Range::InvalidRange()) {
|
| }
|
|
|
| TsfEventRouter::TsfEventRouterDelegate::~TsfEventRouterDelegate() {}
|
| @@ -123,10 +127,20 @@ STDMETHODIMP TsfEventRouter::TsfEventRouterDelegate::OnEndEdit(
|
| if (FAILED(ranges->Next(1, range.Receive(), &fetched_count)))
|
| return S_OK; // Don't care about failures.
|
|
|
| + const ui::Range composition_range = GetCompositionRange(context);
|
| +
|
| + if (!previous_composition_range_.IsValid() && composition_range.IsValid())
|
| + router_->OnTsfStartComposition();
|
| +
|
| // |fetched_count| != 0 means there is at least one range that contains
|
| // updated text.
|
| if (fetched_count != 0)
|
| - router_->OnTextUpdated();
|
| + router_->OnTextUpdated(composition_range);
|
| +
|
| + if (previous_composition_range_.IsValid() && !composition_range.IsValid())
|
| + router_->OnTsfEndComposition();
|
| +
|
| + previous_composition_range_ = composition_range;
|
| return S_OK;
|
| }
|
|
|
| @@ -198,23 +212,39 @@ void TsfEventRouter::TsfEventRouterDelegate::SetManager(
|
| }
|
|
|
| bool TsfEventRouter::TsfEventRouterDelegate::IsImeComposing() {
|
| - return context_ && IsImeComposingInternal(context_);
|
| + return context_ && GetCompositionRange(context_).IsValid();
|
| }
|
|
|
| // static
|
| -bool TsfEventRouter::TsfEventRouterDelegate::IsImeComposingInternal(
|
| +ui::Range TsfEventRouter::TsfEventRouterDelegate::GetCompositionRange(
|
| ITfContext* context) {
|
| DCHECK(context);
|
| base::win::ScopedComPtr<ITfContextComposition> context_composition;
|
| if (FAILED(context_composition.QueryFrom(context)))
|
| - return false;
|
| + return ui::Range::InvalidRange();
|
| base::win::ScopedComPtr<IEnumITfCompositionView> enum_composition_view;
|
| if (FAILED(context_composition->EnumCompositions(
|
| enum_composition_view.Receive())))
|
| - return false;
|
| + return ui::Range::InvalidRange();
|
| base::win::ScopedComPtr<ITfCompositionView> composition_view;
|
| - return enum_composition_view->Next(1, composition_view.Receive(),
|
| - NULL) == S_OK;
|
| + if (enum_composition_view->Next(1, composition_view.Receive(),
|
| + NULL) != S_OK)
|
| + return ui::Range::InvalidRange();
|
| +
|
| + base::win::ScopedComPtr<ITfRange> range;
|
| + if (FAILED(composition_view->GetRange(range.Receive())))
|
| + return ui::Range::InvalidRange();
|
| +
|
| + base::win::ScopedComPtr<ITfRangeACP> range_acp;
|
| + if (FAILED(range_acp.QueryFrom(range)))
|
| + return ui::Range::InvalidRange();
|
| +
|
| + LONG start = 0;
|
| + LONG length = 0;
|
| + if (FAILED(range_acp->GetExtent(&start, &length)))
|
| + return ui::Range::InvalidRange();
|
| +
|
| + return ui::Range(start, start + length);
|
| }
|
|
|
| bool TsfEventRouter::TsfEventRouterDelegate::IsCandidateWindowInternal(
|
| @@ -254,20 +284,28 @@ TsfEventRouter::~TsfEventRouter() {
|
| }
|
| }
|
|
|
| -void TsfEventRouter::SetManager(ITfThreadMgr* thread_manager) {
|
| - delegate_->SetManager(thread_manager);
|
| -}
|
| -
|
| bool TsfEventRouter::IsImeComposing() {
|
| return delegate_->IsImeComposing();
|
| }
|
|
|
| -void TsfEventRouter::OnTextUpdated() {
|
| - observer_->OnTextUpdated();
|
| -}
|
| -
|
| void TsfEventRouter::OnCandidateWindowCountChanged(size_t window_count) {
|
| observer_->OnCandidateWindowCountChanged(window_count);
|
| }
|
|
|
| +void TsfEventRouter::OnTsfStartComposition() {
|
| + observer_->OnTsfStartComposition();
|
| +}
|
| +
|
| +void TsfEventRouter::OnTextUpdated(const ui::Range& composition_range) {
|
| + observer_->OnTextUpdated(composition_range);
|
| +}
|
| +
|
| +void TsfEventRouter::OnTsfEndComposition() {
|
| + observer_->OnTsfEndComposition();
|
| +}
|
| +
|
| +void TsfEventRouter::SetManager(ITfThreadMgr* thread_manager) {
|
| + delegate_->SetManager(thread_manager);
|
| +}
|
| +
|
| } // namespace ui
|
|
|