summaryrefslogtreecommitdiffstats
path: root/win8/metro_driver
diff options
context:
space:
mode:
authoryukawa@chromium.org <yukawa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-12-13 08:51:56 +0000
committeryukawa@chromium.org <yukawa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-12-13 08:51:56 +0000
commitf45eb9cbb423bddaacfa84992a5a6fdef395993a (patch)
treee7e0dc88acb3e810188134aade1851806a44275a /win8/metro_driver
parent9f13938449350a6f118b7cadd7a70055d1a74b05 (diff)
downloadchromium_src-f45eb9cbb423bddaacfa84992a5a6fdef395993a.zip
chromium_src-f45eb9cbb423bddaacfa84992a5a6fdef395993a.tar.gz
chromium_src-f45eb9cbb423bddaacfa84992a5a6fdef395993a.tar.bz2
Ash: Tell the browser process of the visibility of IME's popup UI
This is one of supplemental CLs to port full Desktop IME features into Ash mode. Rationale: Some components in Chrome are interested in whether an IME is showing its own popup window such as the candidate window. OmniBox is one example (see Issue 326774). W3C IME API on which kochi@ is currently working also relies on this information. Implementation memo: This CL uses SetWinEventHook API to monitor the some accessibility events that are generated by IMEs. The parameters passed to SetWinEventHook are carefully chosen so the delegate is called back on the UI thread even when an IME generates the accessibility events on a background thread (actually MS-IME on Windows 8.1 seems to be doing this). BUG=238585, 326774 TEST=manually done on Windows 8.1 with MS-IME Japanese Review URL: https://codereview.chromium.org/101333006 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@240555 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'win8/metro_driver')
-rw-r--r--win8/metro_driver/chrome_app_view_ash.cc25
-rw-r--r--win8/metro_driver/chrome_app_view_ash.h5
-rw-r--r--win8/metro_driver/ime/ime.gypi5
-rw-r--r--win8/metro_driver/ime/ime_popup_monitor.cc82
-rw-r--r--win8/metro_driver/ime/ime_popup_monitor.h19
-rw-r--r--win8/metro_driver/ime/ime_popup_observer.h27
6 files changed, 162 insertions, 1 deletions
diff --git a/win8/metro_driver/chrome_app_view_ash.cc b/win8/metro_driver/chrome_app_view_ash.cc
index 91eec0a..f4d980a 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/ime_popup_monitor.h"
#include "win8/metro_driver/ime/input_source.h"
#include "win8/metro_driver/ime/text_service.h"
#include "win8/metro_driver/metro_driver.h"
@@ -639,6 +640,9 @@ ChromeAppViewAsh::Run() {
OnInputSourceChanged();
}
+ // Start receiving IME popup window notifications.
+ metro_driver::AddImePopupObserver(this);
+
// 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();
@@ -650,6 +654,7 @@ ChromeAppViewAsh::Run() {
IFACEMETHODIMP
ChromeAppViewAsh::Uninitialize() {
DVLOG(1) << __FUNCTION__;
+ metro_driver::RemoveImePopupObserver(this);
input_source_.reset();
text_service_.reset();
window_ = nullptr;
@@ -843,6 +848,26 @@ void ChromeAppViewAsh::OnImeUpdateTextInputClient(
text_service_->OnDocumentChanged(input_scopes, character_bounds);
}
+void ChromeAppViewAsh::OnImePopupChanged(ImePopupObserver::EventType event) {
+ if (!ui_channel_)
+ return;
+ switch (event) {
+ case ImePopupObserver::kPopupShown:
+ ui_channel_->Send(new MetroViewerHostMsg_ImeCandidatePopupChanged(true));
+ return;
+ case ImePopupObserver::kPopupHidden:
+ ui_channel_->Send(new MetroViewerHostMsg_ImeCandidatePopupChanged(false));
+ return;
+ case ImePopupObserver::kPopupUpdated:
+ // TODO(kochi): Support this event for W3C IME API proposal.
+ // See crbug.com/238585.
+ return;
+ default:
+ NOTREACHED() << "unknown event type: " << event;
+ return;
+ }
+}
+
void ChromeAppViewAsh::OnInputSourceChanged() {
if (!input_source_)
return;
diff --git a/win8/metro_driver/chrome_app_view_ash.h b/win8/metro_driver/chrome_app_view_ash.h
index 7517502..f657792 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/ime_popup_observer.h"
#include "win8/metro_driver/ime/input_source_observer.h"
#include "win8/metro_driver/ime/text_service_delegate.h"
@@ -46,6 +47,7 @@ struct MetroViewerHostMsg_SaveAsDialogParams;
class ChromeAppViewAsh
: public mswr::RuntimeClass<winapp::Core::IFrameworkView>,
+ public metro_driver::ImePopupObserver,
public metro_driver::InputSourceObserver,
public metro_driver::TextServiceDelegate {
public:
@@ -105,6 +107,9 @@ class ChromeAppViewAsh
private:
+ // ImePopupObserver overrides.
+ virtual void OnImePopupChanged(ImePopupObserver::EventType event) OVERRIDE;
+
// InputSourceObserver overrides.
virtual void OnInputSourceChanged() OVERRIDE;
diff --git a/win8/metro_driver/ime/ime.gypi b/win8/metro_driver/ime/ime.gypi
index f787f2a..ba9db46 100644
--- a/win8/metro_driver/ime/ime.gypi
+++ b/win8/metro_driver/ime/ime.gypi
@@ -1,9 +1,12 @@
-# Copyright 2013 The Chromium Authors. All rights reserved.
+# Copyright (c) 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.
{
'sources': [
+ 'ime_popup_monitor.cc',
+ 'ime_popup_monitor.h',
+ 'ime_popup_observer.h',
'input_scope.cc',
'input_scope.h',
'input_source.cc',
diff --git a/win8/metro_driver/ime/ime_popup_monitor.cc b/win8/metro_driver/ime/ime_popup_monitor.cc
new file mode 100644
index 0000000..a6368ae
--- /dev/null
+++ b/win8/metro_driver/ime/ime_popup_monitor.cc
@@ -0,0 +1,82 @@
+// 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/ime_popup_monitor.h"
+
+#include <windows.h>
+
+#include "base/logging.h"
+#include "base/message_loop/message_loop.h"
+#include "win8/metro_driver/ime/ime_popup_observer.h"
+
+namespace metro_driver {
+namespace {
+
+ImePopupObserver* g_observer_ = NULL;
+HWINEVENTHOOK g_hook_handle_ = NULL;
+
+void CALLBACK ImeEventCallback(HWINEVENTHOOK win_event_hook_handle,
+ DWORD event,
+ HWND window_handle,
+ LONG object_id,
+ LONG child_id,
+ DWORD event_thread,
+ DWORD event_time) {
+ // This function is registered to SetWinEventHook to be called back on the UI
+ // thread.
+ DCHECK(base::MessageLoop::current()->IsType(base::MessageLoop::TYPE_UI));
+
+ if (!g_observer_)
+ return;
+ switch (event) {
+ case EVENT_OBJECT_IME_SHOW:
+ g_observer_->OnImePopupChanged(ImePopupObserver::kPopupShown);
+ return;
+ case EVENT_OBJECT_IME_HIDE:
+ g_observer_->OnImePopupChanged(ImePopupObserver::kPopupHidden);
+ return;
+ case EVENT_OBJECT_IME_CHANGE:
+ g_observer_->OnImePopupChanged(ImePopupObserver::kPopupUpdated);
+ return;
+ }
+}
+
+} // namespace
+
+void AddImePopupObserver(ImePopupObserver* observer) {
+ CHECK(g_observer_ == NULL)
+ << "Currently only one observer is supported at the same time.";
+ g_observer_ = observer;
+
+ // IMEs running under immersive mode are supposed to generate WinEvent
+ // whenever their popup UI such as candidate window is shown, updated, and
+ // hidden to support accessibility applications.
+ // http://msdn.microsoft.com/en-us/library/windows/apps/hh967425.aspx#accessibility
+ // Note that there is another mechanism in TSF, called ITfUIElementSink, to
+ // subscribe when the visibility of an IME's UI element is changed. However,
+ // MS-IME running under immersive mode does not fully support this API.
+ // Thus, WinEvent is more reliable for this purpose.
+ g_hook_handle_ = SetWinEventHook(
+ EVENT_OBJECT_IME_SHOW,
+ EVENT_OBJECT_IME_CHANGE,
+ NULL,
+ ImeEventCallback,
+ GetCurrentProcessId(), // monitor the metro_driver process only
+ 0, // hook all threads because MS-IME emits WinEvent in a worker thread
+ WINEVENT_OUTOFCONTEXT); // allows us to receive message in the UI thread
+ LOG_IF(ERROR, !g_hook_handle_) << "SetWinEventHook failed.";
+}
+
+void RemoveImePopupObserver(ImePopupObserver* observer) {
+ if (g_observer_ != observer)
+ return;
+ g_observer_ = NULL;
+ if (!g_hook_handle_)
+ return;
+ const bool unhook_succeeded = !!UnhookWinEvent(g_hook_handle_);
+ LOG_IF(ERROR, !unhook_succeeded) << "UnhookWinEvent failed.";
+ g_hook_handle_ = NULL;
+}
+
+} // namespace metro_driver
diff --git a/win8/metro_driver/ime/ime_popup_monitor.h b/win8/metro_driver/ime/ime_popup_monitor.h
new file mode 100644
index 0000000..3bf6558
--- /dev/null
+++ b/win8/metro_driver/ime/ime_popup_monitor.h
@@ -0,0 +1,19 @@
+// 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_IME_POPUP_MONITOR_H_
+#define WIN8_METRO_DRIVER_IME_IME_POPUP_MONITOR_H_
+
+namespace metro_driver {
+
+class ImePopupObserver;
+
+// Adds/Removes ImePopupObserver. Currently only one observer is supported at
+// the same time.
+void AddImePopupObserver(ImePopupObserver* observer);
+void RemoveImePopupObserver(ImePopupObserver* observer);
+
+} // namespace metro_driver
+
+#endif // WIN8_METRO_DRIVER_IME_IME_POPUP_MONITOR_H_
diff --git a/win8/metro_driver/ime/ime_popup_observer.h b/win8/metro_driver/ime/ime_popup_observer.h
new file mode 100644
index 0000000..b871084
--- /dev/null
+++ b/win8/metro_driver/ime/ime_popup_observer.h
@@ -0,0 +1,27 @@
+// 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_IME_POPUP_OBSERVER_H_
+#define WIN8_METRO_DRIVER_IME_IME_POPUP_OBSERVER_H_
+
+namespace metro_driver {
+
+// An observer interface implemented by objects that want to be informed when
+// an IME shows or hides its popup window.
+class ImePopupObserver {
+ public:
+ enum EventType {
+ kPopupShown,
+ kPopupHidden,
+ kPopupUpdated,
+ };
+ virtual ~ImePopupObserver() {}
+
+ // Called whenever an IME's popup window is changed.
+ virtual void OnImePopupChanged(EventType type) = 0;
+};
+
+} // namespace metro_driver
+
+#endif // WIN8_METRO_DRIVER_IME_IME_POPUP_OBSERVER_H_