Commit fe7e213c authored by Siye Liu's avatar Siye Liu Committed by Commit Bot

Notify input method about input type change in omnibox during CJK IME

On Windows platform, omnibox has a special handling that if the input
method is Chinese, Japanese or Korean, then the input type of is changed
to TEXT_INPUT_TYPE_SEARCH. We should notify input mothod that the input
type has been changed.

Bug: 1108845
Change-Id: I0266d9617277696ccb8bfa42ad76f9cbc3d802f3
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2314686
Commit-Queue: Siye Liu <siliu@microsoft.com>
Reviewed-by: default avatarMichael Wasserman <msw@chromium.org>
Reviewed-by: default avatarYohei Yukawa <yukawa@chromium.org>
Cr-Commit-Position: refs/heads/master@{#791443}
parent c1f75b24
......@@ -657,23 +657,23 @@ void OmniboxViewViews::ExecuteCommand(int command_id, int event_flags) {
}
}
ui::TextInputType OmniboxViewViews::GetTextInputType() const {
ui::TextInputType input_type = views::Textfield::GetTextInputType();
void OmniboxViewViews::OnInputMethodChanged() {
#if defined(OS_WIN)
// We'd like to set the text input type to TEXT_INPUT_TYPE_URL, because this
// triggers URL-specific layout in software keyboards, e.g. adding top-level
// "/" and ".com" keys for English. However, this also causes IMEs to default
// to Latin character mode, which makes entering search queries difficult for
// IME users. Therefore, we try to guess whether an IME will be used based on
// the input language, and set the input type accordingly.
#if defined(OS_WIN)
if (input_type != ui::TEXT_INPUT_TYPE_NONE && location_bar_view_) {
if (location_bar_view_) {
ui::InputMethod* input_method =
location_bar_view_->GetWidget()->GetInputMethod();
if (input_method && input_method->IsInputLocaleCJK())
return ui::TEXT_INPUT_TYPE_SEARCH;
SetTextInputType(ui::TEXT_INPUT_TYPE_SEARCH);
else
SetTextInputType(ui::TEXT_INPUT_TYPE_URL);
}
#endif
return input_type;
}
void OmniboxViewViews::AddedToWidget() {
......
......@@ -148,7 +148,7 @@ class OmniboxViewViews : public OmniboxView,
void OnMouseReleased(const ui::MouseEvent& event) override;
void OnPaint(gfx::Canvas* canvas) override;
void ExecuteCommand(int command_id, int event_flags) override;
ui::TextInputType GetTextInputType() const override;
void OnInputMethodChanged() override;
void AddedToWidget() override;
void RemovedFromWidget() override;
base::string16 GetLabelForCommandId(int command_id) const override;
......
......@@ -38,7 +38,9 @@
#include "ui/accessibility/ax_node_data.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/clipboard/scoped_clipboard_writer.h"
#include "ui/base/ime/init/input_method_factory.h"
#include "ui/base/ime/input_method.h"
#include "ui/base/ime/mock_input_method.h"
#include "ui/base/ime/text_edit_commands.h"
#include "ui/base/ime/text_input_client.h"
#include "ui/base/test/ui_controls.h"
......@@ -810,4 +812,55 @@ IN_PROC_BROWSER_TEST_F(OmniboxViewViewsUIATest, AccessibleOmnibox) {
close_waiter.Wait();
EXPECT_FALSE(omnibox_view->model()->popup_model()->IsOpen());
}
namespace {
// MockInputMethod ------------------------------------------------------------
class OmniBoxMockInputMethod : public ui::MockInputMethod {
public:
OmniBoxMockInputMethod() : ui::MockInputMethod(nullptr) {}
bool IsInputLocaleCJK() const override { return input_locale_cjk; }
void SetInputLocaleCJK(bool is_cjk) { input_locale_cjk = is_cjk; }
private:
bool input_locale_cjk = false;
};
} // namespace
class OmniboxViewViewsIMETest : public OmniboxViewViewsTest {
public:
OmniboxViewViewsIMETest() {}
void SetUp() override {
input_method_ = new OmniBoxMockInputMethod();
// transfers ownership.
ui::SetUpInputMethodForTesting(input_method_);
InProcessBrowserTest::SetUp();
}
protected:
void SetUpCommandLine(base::CommandLine* command_line) override {
OmniboxViewViewsTest::SetUpCommandLine(command_line);
command_line->AppendSwitch(switches::kEnableExperimentalUIAutomation);
}
OmniBoxMockInputMethod* input_method_ = nullptr;
};
IN_PROC_BROWSER_TEST_F(OmniboxViewViewsIMETest, TextInputTypeChangedTest) {
chrome::FocusLocationBar(browser());
OmniboxView* view = nullptr;
ASSERT_NO_FATAL_FAILURE(GetOmniboxViewForBrowser(browser(), &view));
OmniboxViewViews* omnibox_view_views = static_cast<OmniboxViewViews*>(view);
ui::InputMethod* input_method =
omnibox_view_views->GetWidget()->GetInputMethod();
EXPECT_EQ(input_method, input_method_);
EXPECT_EQ(ui::TEXT_INPUT_TYPE_URL, omnibox_view_views->GetTextInputType());
input_method_->SetInputLocaleCJK(/*is_cjk*/ true);
omnibox_view_views->OnInputMethodChanged();
EXPECT_EQ(ui::TEXT_INPUT_TYPE_SEARCH, omnibox_view_views->GetTextInputType());
input_method_->SetInputLocaleCJK(/*is_cjk*/ false);
omnibox_view_views->OnInputMethodChanged();
EXPECT_EQ(ui::TEXT_INPUT_TYPE_URL, omnibox_view_views->GetTextInputType());
}
#endif // OS_WIN
......@@ -111,6 +111,10 @@ class TSFBridgeImpl : public TSFBridge {
// An ITfThreadMgr object to be used in focus and document management.
Microsoft::WRL::ComPtr<ITfThreadMgr> thread_manager_;
// An ITfInputProcessorProfiles object to be used to get current language
// locale profile.
Microsoft::WRL::ComPtr<ITfInputProcessorProfiles> input_processor_profiles_;
// A map from TextInputType to an editable document for TSF. We use multiple
// TSF documents that have different InputScopes and TSF attributes based on
// the TextInputType associated with the target document. For a TextInputType
......@@ -134,6 +138,9 @@ class TSFBridgeImpl : public TSFBridge {
// Handle to ITfKeyTraceEventSink.
DWORD key_trace_sink_cookie_ = 0;
// Handle to ITfLanguageProfileNotifySink
DWORD language_profile_cookie_ = 0;
DISALLOW_COPY_AND_ASSIGN(TSFBridgeImpl);
};
......@@ -149,6 +156,11 @@ TSFBridgeImpl::~TSFBridgeImpl() {
if (SUCCEEDED(thread_manager_->QueryInterface(IID_PPV_ARGS(&source)))) {
source->UnadviseSink(key_trace_sink_cookie_);
}
Microsoft::WRL::ComPtr<ITfSource> language_source;
if (SUCCEEDED(input_processor_profiles_->QueryInterface(
IID_PPV_ARGS(&language_source)))) {
language_source->UnadviseSink(language_profile_cookie_);
}
}
for (TSFDocumentMap::iterator it = tsf_document_map_.begin();
......@@ -173,6 +185,13 @@ bool TSFBridgeImpl::Initialize() {
return false;
}
if (FAILED(::CoCreateInstance(CLSID_TF_InputProcessorProfiles, nullptr,
CLSCTX_ALL,
IID_PPV_ARGS(&input_processor_profiles_)))) {
DVLOG(1) << "Failed to create InputProcessorProfiles instance.";
return false;
}
if (FAILED(::CoCreateInstance(CLSID_TF_ThreadMgr, nullptr, CLSCTX_ALL,
IID_PPV_ARGS(&thread_manager_)))) {
DVLOG(1) << "Failed to create ThreadManager instance.";
......@@ -421,6 +440,21 @@ bool TSFBridgeImpl::CreateDocumentManager(TSFTextStore* text_store,
return false;
}
Microsoft::WRL::ComPtr<ITfSource> language_source;
if (FAILED(input_processor_profiles_->QueryInterface(
IID_PPV_ARGS(&language_source)))) {
DVLOG(1) << "Failed to get source_ITfInputProcessorProfiles.";
return false;
}
if (FAILED(
language_source->AdviseSink(IID_ITfLanguageProfileNotifySink,
static_cast<ITfTextEditSink*>(text_store),
&language_profile_cookie_))) {
DVLOG(1) << "AdviseSink for language profile notify sink failed.";
return false;
}
if (*source_cookie == TF_INVALID_COOKIE) {
DVLOG(1) << "The result of cookie is invalid.";
return false;
......
......@@ -81,6 +81,8 @@ HRESULT TSFTextStore::QueryInterface(REFIID iid, void** result) {
*result = static_cast<ITextStoreACP*>(this);
} else if (iid == IID_ITfContextOwnerCompositionSink) {
*result = static_cast<ITfContextOwnerCompositionSink*>(this);
} else if (iid == IID_ITfLanguageProfileNotifySink) {
*result = static_cast<ITfLanguageProfileNotifySink*>(this);
} else if (iid == IID_ITfTextEditSink) {
*result = static_cast<ITfTextEditSink*>(this);
} else if (iid == IID_ITfKeyTraceEventSink) {
......@@ -841,6 +843,15 @@ HRESULT TSFTextStore::OnEndComposition(ITfCompositionView* composition_view) {
return S_OK;
}
HRESULT TSFTextStore::OnLanguageChange(LANGID langid, BOOL* pfAccept) {
return S_OK;
}
HRESULT TSFTextStore::OnLanguageChanged() {
if (text_input_client_)
text_input_client_->OnInputMethodChanged();
return S_OK;
}
HRESULT TSFTextStore::OnKeyTraceDown(WPARAM wParam, LPARAM lParam) {
// fire the event right away if we're in composition
if (has_composition_range_) {
......
......@@ -102,6 +102,7 @@ class TextInputClient;
class COMPONENT_EXPORT(UI_BASE_IME_WIN) TSFTextStore
: public ITextStoreACP,
public ITfContextOwnerCompositionSink,
public ITfLanguageProfileNotifySink,
public ITfKeyTraceEventSink,
public ITfTextEditSink {
public:
......@@ -216,6 +217,10 @@ class COMPONENT_EXPORT(UI_BASE_IME_WIN) TSFTextStore
IFACEMETHODIMP OnEndComposition(
ITfCompositionView* composition_view) override;
// ITfLanguageProfileNotifySink:
IFACEMETHODIMP OnLanguageChange(LANGID langid, BOOL* pfAccept) override;
IFACEMETHODIMP OnLanguageChanged() override;
// ITfTextEditSink:
IFACEMETHODIMP OnEndEdit(ITfContext* context,
TfEditCookie read_only_edit_cookie,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment