Commit dc1615b4 authored by ananta's avatar ananta Committed by Commit bot

Get IME's to work in Chrome OS mode on Windows 7.

IME support in Chrome OS mode/Windows 8 mode is currently implemented in two parts.
1. Metro driver (Viewer process):
   Here we rely on the Text services framework for IME notifications and relay those
   to the browser process.

2. Chrome Browser:
   The browser initializes the input method via the RemoteInputMethodWin class which initializes
   the input method if the viewer is an immersive process.

Fixes as below:-
1. The metro driver initializes the text services framework by instantiating the CLSID_TF_ThreadMgr
   COM object and requests the ITfThreadMgr2 interface.
   This interface is not implemented for Windows 7. Fix is to use the ITfThreadMgr interface instead
   for Windows 7 and up. This provides all the functionality we need.

2. The metro driver was instantiating a MTA COM apartment. The text services COM objects expect to be
   instantiated in a STA.

3. The AppListService object on Windows attempts to bring up the app list bubble in ASH mode even if we are in desktop
mode. Fix is to avoid that.

4. The IsRemoteInputMethodWinRequired function initialized the remote input method if the viewer was an immersive process.
To ensure that it also works on Windows 7 we check whether the browser process is launched with the kViewerConnect switch.

BUG=421980

Review URL: https://codereview.chromium.org/645683002

Cr-Commit-Position: refs/heads/master@{#299203}
parent dc2433de
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include "chrome/installer/util/browser_distribution.h" #include "chrome/installer/util/browser_distribution.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
#include "ui/app_list/views/app_list_view.h" #include "ui/app_list/views/app_list_view.h"
#include "ui/base/ui_base_switches.h"
#include "ui/base/win/shell.h" #include "ui/base/win/shell.h"
#if defined(GOOGLE_CHROME_BUILD) #if defined(GOOGLE_CHROME_BUILD)
...@@ -49,15 +50,20 @@ ...@@ -49,15 +50,20 @@
// static // static
AppListService* AppListService::Get(chrome::HostDesktopType desktop_type) { AppListService* AppListService::Get(chrome::HostDesktopType desktop_type) {
if (desktop_type == chrome::HOST_DESKTOP_TYPE_ASH) if (desktop_type == chrome::HOST_DESKTOP_TYPE_ASH) {
DCHECK(CommandLine::ForCurrentProcess()->HasSwitch(
switches::kViewerConnect));
return AppListServiceAsh::GetInstance(); return AppListServiceAsh::GetInstance();
}
return AppListServiceWin::GetInstance(); return AppListServiceWin::GetInstance();
} }
// static // static
void AppListService::InitAll(Profile* initial_profile) { void AppListService::InitAll(Profile* initial_profile) {
if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kViewerConnect))
AppListServiceAsh::GetInstance()->Init(initial_profile); AppListServiceAsh::GetInstance()->Init(initial_profile);
AppListServiceWin::GetInstance()->Init(initial_profile); AppListServiceWin::GetInstance()->Init(initial_profile);
} }
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "ui/base/ime/remote_input_method_win.h" #include "ui/base/ime/remote_input_method_win.h"
#include "base/command_line.h"
#include "base/observer_list.h" #include "base/observer_list.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "base/win/metro.h" #include "base/win/metro.h"
...@@ -14,6 +15,7 @@ ...@@ -14,6 +15,7 @@
#include "ui/base/ime/remote_input_method_delegate_win.h" #include "ui/base/ime/remote_input_method_delegate_win.h"
#include "ui/base/ime/text_input_client.h" #include "ui/base/ime/text_input_client.h"
#include "ui/base/ime/win/tsf_input_scope.h" #include "ui/base/ime/win/tsf_input_scope.h"
#include "ui/base/ui_base_switches.h"
#include "ui/events/event.h" #include "ui/events/event.h"
#include "ui/events/event_utils.h" #include "ui/events/event_utils.h"
#include "ui/gfx/rect.h" #include "ui/gfx/rect.h"
...@@ -364,6 +366,10 @@ class RemoteInputMethodWin : public InputMethod, ...@@ -364,6 +366,10 @@ class RemoteInputMethodWin : public InputMethod,
} // namespace } // namespace
bool IsRemoteInputMethodWinRequired(gfx::AcceleratedWidget widget) { bool IsRemoteInputMethodWinRequired(gfx::AcceleratedWidget widget) {
// If the remote input method is already registered then don't do it again.
if (ui::g_public_interface_ && ui::g_private_interface_)
return false;
DWORD process_id = 0; DWORD process_id = 0;
if (GetWindowThreadProcessId(widget, &process_id) == 0) if (GetWindowThreadProcessId(widget, &process_id) == 0)
return false; return false;
...@@ -371,7 +377,9 @@ bool IsRemoteInputMethodWinRequired(gfx::AcceleratedWidget widget) { ...@@ -371,7 +377,9 @@ bool IsRemoteInputMethodWinRequired(gfx::AcceleratedWidget widget) {
PROCESS_QUERY_LIMITED_INFORMATION, FALSE, process_id)); PROCESS_QUERY_LIMITED_INFORMATION, FALSE, process_id));
if (!process_handle.IsValid()) if (!process_handle.IsValid())
return false; return false;
return base::win::IsProcessImmersive(process_handle.Get()); return base::win::IsProcessImmersive(process_handle.Get()) ||
CommandLine::ForCurrentProcess()->HasSwitch(
switches::kViewerConnect);
} }
RemoteInputMethodPrivateWin::RemoteInputMethodPrivateWin() {} RemoteInputMethodPrivateWin::RemoteInputMethodPrivateWin() {}
......
...@@ -92,7 +92,7 @@ namespace { ...@@ -92,7 +92,7 @@ namespace {
// TF_SENTENCEMODE_PHRASEPREDICT to emulate IMM32 behavior. This value is // TF_SENTENCEMODE_PHRASEPREDICT to emulate IMM32 behavior. This value is
// managed per thread, thus setting this value at once is sufficient. This // managed per thread, thus setting this value at once is sufficient. This
// value never affects non-Japanese IMEs. // value never affects non-Japanese IMEs.
bool InitializeSentenceMode(ITfThreadMgr2* thread_manager, bool InitializeSentenceMode(ITfThreadMgr* thread_manager,
TfClientId client_id) { TfClientId client_id) {
base::win::ScopedComPtr<ITfCompartmentMgr> thread_compartment_manager; base::win::ScopedComPtr<ITfCompartmentMgr> thread_compartment_manager;
HRESULT hr = thread_compartment_manager.QueryFrom(thread_manager); HRESULT hr = thread_compartment_manager.QueryFrom(thread_manager);
...@@ -224,7 +224,7 @@ class DocumentBinding { ...@@ -224,7 +224,7 @@ class DocumentBinding {
} }
static scoped_ptr<DocumentBinding> Create( static scoped_ptr<DocumentBinding> Create(
ITfThreadMgr2* thread_manager, ITfThreadMgr* thread_manager,
TfClientId client_id, TfClientId client_id,
const std::vector<InputScope>& input_scopes, const std::vector<InputScope>& input_scopes,
HWND window_handle, HWND window_handle,
...@@ -232,7 +232,7 @@ class DocumentBinding { ...@@ -232,7 +232,7 @@ class DocumentBinding {
base::win::ScopedComPtr<ITfDocumentMgr> document_manager; base::win::ScopedComPtr<ITfDocumentMgr> document_manager;
HRESULT hr = thread_manager->CreateDocumentMgr(document_manager.Receive()); HRESULT hr = thread_manager->CreateDocumentMgr(document_manager.Receive());
if (FAILED(hr)) { if (FAILED(hr)) {
LOG(ERROR) << "ITfThreadMgr2::CreateDocumentMgr failed. hr = " << hr; LOG(ERROR) << "ITfThreadMgr::CreateDocumentMgr failed. hr = " << hr;
return scoped_ptr<DocumentBinding>(); return scoped_ptr<DocumentBinding>();
} }
...@@ -316,7 +316,7 @@ class DocumentBinding { ...@@ -316,7 +316,7 @@ class DocumentBinding {
class TextServiceImpl : public TextService, class TextServiceImpl : public TextService,
public TextStoreDelegate { public TextStoreDelegate {
public: public:
TextServiceImpl(ITfThreadMgr2* thread_manager, TextServiceImpl(ITfThreadMgr* thread_manager,
TfClientId client_id, TfClientId client_id,
HWND window_handle, HWND window_handle,
TextServiceDelegate* delegate) TextServiceDelegate* delegate)
...@@ -368,7 +368,7 @@ class TextServiceImpl : public TextService, ...@@ -368,7 +368,7 @@ class TextServiceImpl : public TextService,
} }
HRESULT hr = thread_manager_->SetFocus(document_manager); HRESULT hr = thread_manager_->SetFocus(document_manager);
if (FAILED(hr)) { if (FAILED(hr)) {
LOG(ERROR) << "ITfThreadMgr2::SetFocus failed. hr = " << hr; LOG(ERROR) << "ITfThreadMgr::SetFocus failed. hr = " << hr;
return; return;
} }
} }
...@@ -446,7 +446,7 @@ class TextServiceImpl : public TextService, ...@@ -446,7 +446,7 @@ class TextServiceImpl : public TextService,
HWND window_handle_; HWND window_handle_;
TextServiceDelegate* delegate_; TextServiceDelegate* delegate_;
scoped_ptr<DocumentBinding> current_document_; scoped_ptr<DocumentBinding> current_document_;
base::win::ScopedComPtr<ITfThreadMgr2> thread_manager_; base::win::ScopedComPtr<ITfThreadMgr> thread_manager_;
// A vector of InputScope enumeration, which represents the document type of // A vector of InputScope enumeration, which represents the document type of
// the focused text field. Note that in our IPC message protocol, an empty // the focused text field. Note that in our IPC message protocol, an empty
...@@ -466,7 +466,7 @@ scoped_ptr<TextService> ...@@ -466,7 +466,7 @@ scoped_ptr<TextService>
CreateTextService(TextServiceDelegate* delegate, HWND window_handle) { CreateTextService(TextServiceDelegate* delegate, HWND window_handle) {
if (!delegate) if (!delegate)
return scoped_ptr<TextService>(); return scoped_ptr<TextService>();
base::win::ScopedComPtr<ITfThreadMgr2> thread_manager; base::win::ScopedComPtr<ITfThreadMgr> thread_manager;
HRESULT hr = thread_manager.CreateInstance(CLSID_TF_ThreadMgr); HRESULT hr = thread_manager.CreateInstance(CLSID_TF_ThreadMgr);
if (FAILED(hr)) { if (FAILED(hr)) {
LOG(ERROR) << "Failed to create instance of CLSID_TF_ThreadMgr. hr = " LOG(ERROR) << "Failed to create instance of CLSID_TF_ThreadMgr. hr = "
...@@ -474,9 +474,9 @@ CreateTextService(TextServiceDelegate* delegate, HWND window_handle) { ...@@ -474,9 +474,9 @@ CreateTextService(TextServiceDelegate* delegate, HWND window_handle) {
return scoped_ptr<TextService>(); return scoped_ptr<TextService>();
} }
TfClientId client_id = TF_CLIENTID_NULL; TfClientId client_id = TF_CLIENTID_NULL;
hr = thread_manager->ActivateEx(&client_id, 0); hr = thread_manager->Activate(&client_id);
if (FAILED(hr)) { if (FAILED(hr)) {
LOG(ERROR) << "ITfThreadMgr2::ActivateEx failed. hr = " << hr; LOG(ERROR) << "ITfThreadMgr::Activate failed. hr = " << hr;
return scoped_ptr<TextService>(); return scoped_ptr<TextService>();
} }
if (!InitializeSentenceMode(thread_manager, client_id)) { if (!InitializeSentenceMode(thread_manager, client_id)) {
......
...@@ -1229,7 +1229,7 @@ class CoreApplicationWin7Emulation ...@@ -1229,7 +1229,7 @@ class CoreApplicationWin7Emulation
mswr::ComPtr<winapp::Core::ICoreApplication> InitWindows7() { mswr::ComPtr<winapp::Core::ICoreApplication> InitWindows7() {
HRESULT hr = ::CoInitializeEx(NULL, COINIT_MULTITHREADED); HRESULT hr = ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
if (FAILED(hr)) if (FAILED(hr))
CHECK(false); CHECK(false);
return mswr::Make<CoreApplicationWin7Emulation>(); return mswr::Make<CoreApplicationWin7Emulation>();
......
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