From dc1615b4060ed2a879ee74e0a7c8c4a811b22ec6 Mon Sep 17 00:00:00 2001 From: ananta Date: Fri, 10 Oct 2014 15:24:46 -0700 Subject: 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} --- .../ui/views/app_list/win/app_list_service_win.cc | 10 ++++++++-- ui/base/ime/remote_input_method_win.cc | 10 +++++++++- win8/metro_driver/ime/text_service.cc | 18 +++++++++--------- win8/metro_driver/metro_driver_win7.cc | 2 +- 4 files changed, 27 insertions(+), 13 deletions(-) diff --git a/chrome/browser/ui/views/app_list/win/app_list_service_win.cc b/chrome/browser/ui/views/app_list/win/app_list_service_win.cc index bdbc152..3350ef4 100644 --- a/chrome/browser/ui/views/app_list/win/app_list_service_win.cc +++ b/chrome/browser/ui/views/app_list/win/app_list_service_win.cc @@ -38,6 +38,7 @@ #include "chrome/installer/util/browser_distribution.h" #include "content/public/browser/browser_thread.h" #include "ui/app_list/views/app_list_view.h" +#include "ui/base/ui_base_switches.h" #include "ui/base/win/shell.h" #if defined(GOOGLE_CHROME_BUILD) @@ -49,15 +50,20 @@ // static 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 AppListServiceWin::GetInstance(); } // static void AppListService::InitAll(Profile* initial_profile) { - AppListServiceAsh::GetInstance()->Init(initial_profile); + if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kViewerConnect)) + AppListServiceAsh::GetInstance()->Init(initial_profile); + AppListServiceWin::GetInstance()->Init(initial_profile); } diff --git a/ui/base/ime/remote_input_method_win.cc b/ui/base/ime/remote_input_method_win.cc index b01a39c..0b75c07 100644 --- a/ui/base/ime/remote_input_method_win.cc +++ b/ui/base/ime/remote_input_method_win.cc @@ -4,6 +4,7 @@ #include "ui/base/ime/remote_input_method_win.h" +#include "base/command_line.h" #include "base/observer_list.h" #include "base/strings/utf_string_conversions.h" #include "base/win/metro.h" @@ -14,6 +15,7 @@ #include "ui/base/ime/remote_input_method_delegate_win.h" #include "ui/base/ime/text_input_client.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_utils.h" #include "ui/gfx/rect.h" @@ -364,6 +366,10 @@ class RemoteInputMethodWin : public InputMethod, } // namespace 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; if (GetWindowThreadProcessId(widget, &process_id) == 0) return false; @@ -371,7 +377,9 @@ bool IsRemoteInputMethodWinRequired(gfx::AcceleratedWidget widget) { PROCESS_QUERY_LIMITED_INFORMATION, FALSE, process_id)); if (!process_handle.IsValid()) return false; - return base::win::IsProcessImmersive(process_handle.Get()); + return base::win::IsProcessImmersive(process_handle.Get()) || + CommandLine::ForCurrentProcess()->HasSwitch( + switches::kViewerConnect); } RemoteInputMethodPrivateWin::RemoteInputMethodPrivateWin() {} diff --git a/win8/metro_driver/ime/text_service.cc b/win8/metro_driver/ime/text_service.cc index 986288e..cb9421a 100644 --- a/win8/metro_driver/ime/text_service.cc +++ b/win8/metro_driver/ime/text_service.cc @@ -92,7 +92,7 @@ namespace { // TF_SENTENCEMODE_PHRASEPREDICT to emulate IMM32 behavior. This value is // managed per thread, thus setting this value at once is sufficient. This // value never affects non-Japanese IMEs. -bool InitializeSentenceMode(ITfThreadMgr2* thread_manager, +bool InitializeSentenceMode(ITfThreadMgr* thread_manager, TfClientId client_id) { base::win::ScopedComPtr thread_compartment_manager; HRESULT hr = thread_compartment_manager.QueryFrom(thread_manager); @@ -224,7 +224,7 @@ class DocumentBinding { } static scoped_ptr Create( - ITfThreadMgr2* thread_manager, + ITfThreadMgr* thread_manager, TfClientId client_id, const std::vector& input_scopes, HWND window_handle, @@ -232,7 +232,7 @@ class DocumentBinding { base::win::ScopedComPtr document_manager; HRESULT hr = thread_manager->CreateDocumentMgr(document_manager.Receive()); if (FAILED(hr)) { - LOG(ERROR) << "ITfThreadMgr2::CreateDocumentMgr failed. hr = " << hr; + LOG(ERROR) << "ITfThreadMgr::CreateDocumentMgr failed. hr = " << hr; return scoped_ptr(); } @@ -316,7 +316,7 @@ class DocumentBinding { class TextServiceImpl : public TextService, public TextStoreDelegate { public: - TextServiceImpl(ITfThreadMgr2* thread_manager, + TextServiceImpl(ITfThreadMgr* thread_manager, TfClientId client_id, HWND window_handle, TextServiceDelegate* delegate) @@ -368,7 +368,7 @@ class TextServiceImpl : public TextService, } HRESULT hr = thread_manager_->SetFocus(document_manager); if (FAILED(hr)) { - LOG(ERROR) << "ITfThreadMgr2::SetFocus failed. hr = " << hr; + LOG(ERROR) << "ITfThreadMgr::SetFocus failed. hr = " << hr; return; } } @@ -446,7 +446,7 @@ class TextServiceImpl : public TextService, HWND window_handle_; TextServiceDelegate* delegate_; scoped_ptr current_document_; - base::win::ScopedComPtr thread_manager_; + base::win::ScopedComPtr thread_manager_; // A vector of InputScope enumeration, which represents the document type of // the focused text field. Note that in our IPC message protocol, an empty @@ -466,7 +466,7 @@ scoped_ptr CreateTextService(TextServiceDelegate* delegate, HWND window_handle) { if (!delegate) return scoped_ptr(); - base::win::ScopedComPtr thread_manager; + base::win::ScopedComPtr thread_manager; HRESULT hr = thread_manager.CreateInstance(CLSID_TF_ThreadMgr); if (FAILED(hr)) { LOG(ERROR) << "Failed to create instance of CLSID_TF_ThreadMgr. hr = " @@ -474,9 +474,9 @@ CreateTextService(TextServiceDelegate* delegate, HWND window_handle) { return scoped_ptr(); } TfClientId client_id = TF_CLIENTID_NULL; - hr = thread_manager->ActivateEx(&client_id, 0); + hr = thread_manager->Activate(&client_id); if (FAILED(hr)) { - LOG(ERROR) << "ITfThreadMgr2::ActivateEx failed. hr = " << hr; + LOG(ERROR) << "ITfThreadMgr::Activate failed. hr = " << hr; return scoped_ptr(); } if (!InitializeSentenceMode(thread_manager, client_id)) { diff --git a/win8/metro_driver/metro_driver_win7.cc b/win8/metro_driver/metro_driver_win7.cc index 618cfb3..22d6034 100644 --- a/win8/metro_driver/metro_driver_win7.cc +++ b/win8/metro_driver/metro_driver_win7.cc @@ -1229,7 +1229,7 @@ class CoreApplicationWin7Emulation mswr::ComPtr InitWindows7() { - HRESULT hr = ::CoInitializeEx(NULL, COINIT_MULTITHREADED); + HRESULT hr = ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); if (FAILED(hr)) CHECK(false); return mswr::Make(); -- cgit v1.1