diff options
Diffstat (limited to 'win8')
-rw-r--r-- | win8/metro_driver/chrome_app_view_ash.cc | 25 | ||||
-rw-r--r-- | win8/metro_driver/chrome_app_view_ash.h | 5 | ||||
-rw-r--r-- | win8/metro_driver/ime/ime.gypi | 5 | ||||
-rw-r--r-- | win8/metro_driver/ime/ime_popup_monitor.cc | 82 | ||||
-rw-r--r-- | win8/metro_driver/ime/ime_popup_monitor.h | 19 | ||||
-rw-r--r-- | win8/metro_driver/ime/ime_popup_observer.h | 27 |
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_ |