summaryrefslogtreecommitdiffstats
path: root/win8
diff options
context:
space:
mode:
Diffstat (limited to 'win8')
-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_