summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoryukawa@chromium.org <yukawa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-12-11 02:37:21 +0000
committeryukawa@chromium.org <yukawa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-12-11 02:37:21 +0000
commit8be5344d42caeff97ff8eaadf9220fa9383852d1 (patch)
tree8e364e8ca10ba921cd9940ff1ecaa9261f9f7219
parentb9612330073aa910a5b998f4cb96ca17c05271fb (diff)
downloadchromium_src-8be5344d42caeff97ff8eaadf9220fa9383852d1.zip
chromium_src-8be5344d42caeff97ff8eaadf9220fa9383852d1.tar.gz
chromium_src-8be5344d42caeff97ff8eaadf9220fa9383852d1.tar.bz2
Ash: tell the browser process of the LANGID of the active input source
This is a preparation CL to implement 'locale' property proposed in UI Events (formerly called d4e). http://www.w3.org/TR/uievents/#idl-def-KeyboardEventInit On Windows 8/8.1, a user can still choose per-process IME/keyboard layout model. Thus, we need to tell the browser process what IME/keyboard layout is used in the metro_driver process whenever it is changed. BUG=168971 TEST=manually done on Windows 8.1 Review URL: https://codereview.chromium.org/109683002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@239971 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--ui/aura/remote_root_window_host_win.cc11
-rw-r--r--ui/aura/remote_root_window_host_win.h1
-rw-r--r--win8/metro_driver/chrome_app_view_ash.cc23
-rw-r--r--win8/metro_driver/chrome_app_view_ash.h7
-rw-r--r--win8/metro_driver/ime/ime.gypi3
-rw-r--r--win8/metro_driver/ime/input_source.cc170
-rw-r--r--win8/metro_driver/ime/input_source.h36
-rw-r--r--win8/metro_driver/ime/input_source_observer.h26
8 files changed, 277 insertions, 0 deletions
diff --git a/ui/aura/remote_root_window_host_win.cc b/ui/aura/remote_root_window_host_win.cc
index 35dc3a0..f6de429 100644
--- a/ui/aura/remote_root_window_host_win.cc
+++ b/ui/aura/remote_root_window_host_win.cc
@@ -221,6 +221,8 @@ bool RemoteRootWindowHostWin::OnMessageReceived(const IPC::Message& message) {
OnImeCompositionChanged)
IPC_MESSAGE_HANDLER(MetroViewerHostMsg_ImeTextCommitted,
OnImeTextCommitted)
+ IPC_MESSAGE_HANDLER(MetroViewerHostMsg_ImeInputSourceChanged,
+ OnImeInputSourceChanged)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
@@ -674,6 +676,15 @@ void RemoteRootWindowHostWin::OnImeTextCommitted(const string16& text) {
remote_input_method_private->OnTextCommitted(text);
}
+void RemoteRootWindowHostWin::OnImeInputSourceChanged(uint16 language_id,
+ bool is_ime) {
+ ui::RemoteInputMethodPrivateWin* remote_input_method_private =
+ GetRemoteInputMethodPrivate();
+ if (!remote_input_method_private)
+ return;
+ remote_input_method_private->OnInputSourceChanged(language_id, is_ime);
+}
+
void RemoteRootWindowHostWin::DispatchKeyboardMessage(ui::EventType type,
uint32 vkey,
uint32 repeat_count,
diff --git a/ui/aura/remote_root_window_host_win.h b/ui/aura/remote_root_window_host_win.h
index 04bd6bc..a319d27 100644
--- a/ui/aura/remote_root_window_host_win.h
+++ b/ui/aura/remote_root_window_host_win.h
@@ -205,6 +205,7 @@ class AURA_EXPORT RemoteRootWindowHostWin
int32 selection_end,
const std::vector<metro_viewer::UnderlineInfo>& underlines);
void OnImeTextCommitted(const string16& text);
+ void OnImeInputSourceChanged(uint16 language_id, bool is_ime);
// RootWindowHost overrides:
virtual RootWindow* GetRootWindow() OVERRIDE;
diff --git a/win8/metro_driver/chrome_app_view_ash.cc b/win8/metro_driver/chrome_app_view_ash.cc
index 2e96a00..e6525d1 100644
--- a/win8/metro_driver/chrome_app_view_ash.cc
+++ b/win8/metro_driver/chrome_app_view_ash.cc
@@ -24,6 +24,7 @@
#include "ui/events/gestures/gesture_sequence.h"
#include "ui/metro_viewer/metro_viewer_messages.h"
#include "win8/metro_driver/file_picker_ash.h"
+#include "win8/metro_driver/ime/input_source.h"
#include "win8/metro_driver/ime/text_service.h"
#include "win8/metro_driver/metro_driver.h"
#include "win8/metro_driver/winrt_utils.h"
@@ -632,6 +633,13 @@ ChromeAppViewAsh::Run() {
new MetroViewerHostMsg_WindowSizeChanged(rect.right - rect.left,
rect.bottom - rect.top));
+ input_source_ = metro_driver::InputSource::Create();
+ if (input_source_) {
+ input_source_->AddObserver(this);
+ // Send an initial input source.
+ OnInputSourceChanged();
+ }
+
// And post the task that'll do the inner Metro message pumping to it.
ui_loop_.PostTask(FROM_HERE, base::Bind(&RunMessageLoop, dispatcher.Get()));
ui_loop_.Run();
@@ -643,6 +651,7 @@ ChromeAppViewAsh::Run() {
IFACEMETHODIMP
ChromeAppViewAsh::Uninitialize() {
DVLOG(1) << __FUNCTION__;
+ input_source_.reset();
text_service_.reset();
window_ = nullptr;
view_ = nullptr;
@@ -835,6 +844,20 @@ void ChromeAppViewAsh::OnImeUpdateTextInputClient(
text_service_->OnDocumentChanged(input_scopes, character_bounds);
}
+void ChromeAppViewAsh::OnInputSourceChanged() {
+ if (!input_source_)
+ return;
+
+ LANGID langid = 0;
+ bool is_ime = false;
+ if (!input_source_->GetActiveSource(&langid, &is_ime)) {
+ LOG(ERROR) << "GetActiveSource failed";
+ return;
+ }
+ ui_channel_->Send(new MetroViewerHostMsg_ImeInputSourceChanged(langid,
+ is_ime));
+}
+
void ChromeAppViewAsh::OnCompositionChanged(
const string16& text,
int32 selection_start,
diff --git a/win8/metro_driver/chrome_app_view_ash.h b/win8/metro_driver/chrome_app_view_ash.h
index c2e6d42..7517502 100644
--- a/win8/metro_driver/chrome_app_view_ash.h
+++ b/win8/metro_driver/chrome_app_view_ash.h
@@ -15,6 +15,7 @@
#include "base/strings/string16.h"
#include "ui/events/event_constants.h"
#include "win8/metro_driver/direct3d_helper.h"
+#include "win8/metro_driver/ime/input_source_observer.h"
#include "win8/metro_driver/ime/text_service_delegate.h"
namespace base {
@@ -27,6 +28,7 @@ class ChannelProxy;
}
namespace metro_driver {
+class InputSource;
class TextService;
}
@@ -44,6 +46,7 @@ struct MetroViewerHostMsg_SaveAsDialogParams;
class ChromeAppViewAsh
: public mswr::RuntimeClass<winapp::Core::IFrameworkView>,
+ public metro_driver::InputSourceObserver,
public metro_driver::TextServiceDelegate {
public:
ChromeAppViewAsh();
@@ -102,6 +105,9 @@ class ChromeAppViewAsh
private:
+ // InputSourceObserver overrides.
+ virtual void OnInputSourceChanged() OVERRIDE;
+
// TextServiceDelegate overrides.
virtual void OnCompositionChanged(
const string16& text,
@@ -190,6 +196,7 @@ class ChromeAppViewAsh
base::MessageLoop ui_loop_;
// For IME support.
+ scoped_ptr<metro_driver::InputSource> input_source_;
scoped_ptr<metro_driver::TextService> text_service_;
};
diff --git a/win8/metro_driver/ime/ime.gypi b/win8/metro_driver/ime/ime.gypi
index c5d7f1e..f787f2a 100644
--- a/win8/metro_driver/ime/ime.gypi
+++ b/win8/metro_driver/ime/ime.gypi
@@ -6,6 +6,9 @@
'sources': [
'input_scope.cc',
'input_scope.h',
+ 'input_source.cc',
+ 'input_source.h',
+ 'input_source_observer.h',
'text_service.cc',
'text_service.h',
'text_service_delegate.h',
diff --git a/win8/metro_driver/ime/input_source.cc b/win8/metro_driver/ime/input_source.cc
new file mode 100644
index 0000000..dd27380
--- /dev/null
+++ b/win8/metro_driver/ime/input_source.cc
@@ -0,0 +1,170 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "win8/metro_driver/ime/input_source.h"
+
+#include <atlbase.h>
+#include <atlcom.h>
+#include <msctf.h>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/logging.h"
+#include "base/memory/ref_counted.h"
+#include "base/observer_list.h"
+#include "base/win/scoped_comptr.h"
+#include "ui/base/win/atl_module.h"
+#include "win8/metro_driver/ime/input_source_observer.h"
+
+namespace metro_driver {
+namespace {
+
+// An implementation of ITfLanguageProfileNotifySink interface, which will be
+// used to receive notifications when the text input source is changed.
+class ATL_NO_VTABLE InputSourceMonitor
+ : public CComObjectRootEx<CComMultiThreadModel>,
+ public ITfLanguageProfileNotifySink {
+ public:
+ InputSourceMonitor()
+ : cookie_(TF_INVALID_COOKIE) {
+ }
+
+ BEGIN_COM_MAP(InputSourceMonitor)
+ COM_INTERFACE_ENTRY(ITfLanguageProfileNotifySink)
+ END_COM_MAP()
+
+ bool Initialize(ITfSource* source) {
+ DWORD cookie = TF_INVALID_COOKIE;
+ HRESULT hr = source->AdviseSink(IID_ITfLanguageProfileNotifySink,
+ this,
+ &cookie);
+ if (FAILED(hr)) {
+ LOG(ERROR) << "ITfSource::AdviseSink failed. hr = " << hr;
+ return false;
+ }
+ cookie_ = cookie;
+ source_ = source;
+ return true;
+ }
+
+ void SetCallback(base::Closure on_language_chanaged) {
+ on_language_chanaged_ = on_language_chanaged;
+ }
+
+ void Unadvise() {
+ if (cookie_ == TF_INVALID_COOKIE || !source_)
+ return;
+ if (FAILED(source_->UnadviseSink(cookie_)))
+ return;
+ cookie_ = TF_INVALID_COOKIE;
+ source_.Release();
+ }
+
+ private:
+ // ITfLanguageProfileNotifySink overrides:
+ STDMETHOD(OnLanguageChange)(LANGID langid, BOOL *accept) OVERRIDE {
+ if (!accept)
+ return E_INVALIDARG;
+ *accept = TRUE;
+ return S_OK;
+ }
+
+ STDMETHOD(OnLanguageChanged)() OVERRIDE {
+ if (!on_language_chanaged_.is_null())
+ on_language_chanaged_.Run();
+ return S_OK;
+ }
+
+ base::Closure on_language_chanaged_;
+ base::win::ScopedComPtr<ITfSource> source_;
+ DWORD cookie_;
+
+ DISALLOW_COPY_AND_ASSIGN(InputSourceMonitor);
+};
+
+class InputSourceImpl : public InputSource {
+ public:
+ InputSourceImpl(ITfInputProcessorProfileMgr* profile_manager,
+ InputSourceMonitor* monitor)
+ : profile_manager_(profile_manager),
+ monitor_(monitor) {
+ monitor_->SetCallback(base::Bind(&InputSourceImpl::OnLanguageChanged,
+ base::Unretained(this)));
+ }
+ virtual ~InputSourceImpl() {
+ monitor_->SetCallback(base::Closure());
+ monitor_->Unadvise();
+ }
+
+ private:
+ // InputSource overrides.
+ virtual bool GetActiveSource(LANGID* langid, bool* is_ime) OVERRIDE {
+ TF_INPUTPROCESSORPROFILE profile = {};
+ HRESULT hr = profile_manager_->GetActiveProfile(GUID_TFCAT_TIP_KEYBOARD,
+ &profile);
+ if (FAILED(hr)) {
+ LOG(ERROR) << "ITfInputProcessorProfileMgr::GetActiveProfile failed."
+ << " hr = " << hr;
+ return false;
+ }
+ *langid = profile.langid;
+ *is_ime = profile.dwProfileType == TF_PROFILETYPE_INPUTPROCESSOR;
+ return true;
+ }
+ virtual void AddObserver(InputSourceObserver* observer) OVERRIDE {
+ observer_list_.AddObserver(observer);
+ }
+ virtual void RemoveObserver(InputSourceObserver* observer) OVERRIDE {
+ observer_list_.RemoveObserver(observer);
+ }
+ void OnLanguageChanged() {
+ FOR_EACH_OBSERVER(InputSourceObserver,
+ observer_list_,
+ OnInputSourceChanged());
+ }
+
+ base::win::ScopedComPtr<ITfInputProcessorProfileMgr> profile_manager_;
+ scoped_refptr<InputSourceMonitor> monitor_;
+ ObserverList<InputSourceObserver> observer_list_;
+
+ DISALLOW_COPY_AND_ASSIGN(InputSourceImpl);
+};
+
+} // namespace
+
+// static
+scoped_ptr<InputSource> InputSource::Create() {
+ ui::win::CreateATLModuleIfNeeded();
+
+ base::win::ScopedComPtr<ITfInputProcessorProfileMgr> profile_manager;
+ HRESULT hr = profile_manager.CreateInstance(CLSID_TF_InputProcessorProfiles);
+ if (FAILED(hr)) {
+ LOG(ERROR) << "Failed to instantiate CLSID_TF_InputProcessorProfiles."
+ << " hr = " << hr;
+ return scoped_ptr<InputSource>();
+ }
+ base::win::ScopedComPtr<ITfSource> profiles_source;
+ hr = profiles_source.QueryFrom(profile_manager);
+ if (FAILED(hr)) {
+ LOG(ERROR) << "QueryFrom to ITfSource failed. hr = " << hr;
+ return scoped_ptr<InputSource>();
+ }
+
+ CComObject<InputSourceMonitor>* monitor = NULL;
+ hr = CComObject<InputSourceMonitor>::CreateInstance(&monitor);
+ if (FAILED(hr)) {
+ LOG(ERROR) << "CComObject<InputSourceMonitor>::CreateInstance failed."
+ << " hr = " << hr;
+ return scoped_ptr<InputSource>();
+ }
+ if (!monitor->Initialize(profiles_source)) {
+ LOG(ERROR) << "Failed to initialize the monitor.";
+ return scoped_ptr<InputSource>();
+ }
+
+ // Transfer the ownership.
+ return scoped_ptr<InputSource>(new InputSourceImpl(profile_manager, monitor));
+}
+
+} // namespace metro_driver
diff --git a/win8/metro_driver/ime/input_source.h b/win8/metro_driver/ime/input_source.h
new file mode 100644
index 0000000..8b057b2
--- /dev/null
+++ b/win8/metro_driver/ime/input_source.h
@@ -0,0 +1,36 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WIN8_METRO_DRIVER_IME_INPUT_SOURCE_H_
+#define WIN8_METRO_DRIVER_IME_INPUT_SOURCE_H_
+
+#include <Windows.h>
+
+#include "base/memory/scoped_ptr.h"
+
+namespace metro_driver {
+
+class InputSourceObserver;
+
+// An interface through which information about the input source can be
+// retrieved, where an input source represents an IME or a keyboard layout.
+class InputSource {
+ public:
+ virtual ~InputSource() {}
+ // Create an instance. Returns NULL if fails.
+ static scoped_ptr<InputSource> Create();
+
+ // Returns true if |langid| and |is_ime| are filled based on the current
+ // active input source.
+ virtual bool GetActiveSource(LANGID* langid, bool* is_ime) = 0;
+
+ // Adds/Removes an observer to receive notifications when the active input
+ // source is changed.
+ virtual void AddObserver(InputSourceObserver* observer) = 0;
+ virtual void RemoveObserver(InputSourceObserver* observer) = 0;
+};
+
+} // namespace metro_driver
+
+#endif // WIN8_METRO_DRIVER_IME_INPUT_SOURCE_H_
diff --git a/win8/metro_driver/ime/input_source_observer.h b/win8/metro_driver/ime/input_source_observer.h
new file mode 100644
index 0000000..4be77a5
--- /dev/null
+++ b/win8/metro_driver/ime/input_source_observer.h
@@ -0,0 +1,26 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WIN8_METRO_DRIVER_IME_INPUT_SOURCE_OBSERVER_H_
+#define WIN8_METRO_DRIVER_IME_INPUT_SOURCE_OBSERVER_H_
+
+#include <Windows.h>
+
+#include "base/basictypes.h"
+
+namespace metro_driver {
+
+// An observer interface implemented by objects that want to be informed
+// when the active language profile is changed.
+class InputSourceObserver {
+ public:
+ virtual ~InputSourceObserver() {}
+
+ // Called when the active language profile is changed.
+ virtual void OnInputSourceChanged() = 0;
+};
+
+} // namespace metro_driver
+
+#endif // WIN8_METRO_DRIVER_IME_INPUT_SOURCE_OBSERVER_H_