OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "win8/metro_driver/ime/ime_popup_monitor.h" |
| 6 |
| 7 #include <msctf.h> |
| 8 |
| 9 #include "base/logging.h" |
| 10 #include "base/message_loop/message_loop.h" |
| 11 #include "win8/metro_driver/ime/ime_popup_observer.h" |
| 12 |
| 13 namespace metro_driver { |
| 14 namespace { |
| 15 |
| 16 ImePopupObserver* g_observer_ = NULL; |
| 17 HWINEVENTHOOK g_hook_handle_ = NULL; |
| 18 |
| 19 void CALLBACK ImeEventCallback(HWINEVENTHOOK win_event_hook_handle, |
| 20 DWORD event, |
| 21 HWND window_handle, |
| 22 LONG object_id, |
| 23 LONG child_id, |
| 24 DWORD event_thread, |
| 25 DWORD event_time) { |
| 26 DCHECK_EQ(base::MessageLoop::TYPE_UI, base::MessageLoop::current()->type()); |
| 27 if (!g_observer_) |
| 28 return; |
| 29 switch (event) { |
| 30 case EVENT_OBJECT_IME_SHOW: |
| 31 g_observer_->OnCandidatePopupChanged(true); |
| 32 return; |
| 33 case EVENT_OBJECT_IME_HIDE: |
| 34 g_observer_->OnCandidatePopupChanged(false); |
| 35 return; |
| 36 // Note: we never see EVENT_OBJECT_IME_CHANGE here because it is filtered |
| 37 // out when SetWinEventHook API is called. |
| 38 } |
| 39 } |
| 40 |
| 41 } // namespace |
| 42 |
| 43 void AddImePopupObserver(ImePopupObserver* observer) { |
| 44 CHECK(g_observer_ == NULL) << |
| 45 "Currently only one observer is supported at the same time."; |
| 46 g_observer_ = observer; |
| 47 |
| 48 // Unfortunately MS-IME in immersive mode does not fully support |
| 49 // ITfUIElementSink. EVENT_OBJECT_IME_SHOW/EVENT_OBJECT_IME_HIDE is more |
| 50 // reliable in practice. |
| 51 // Caveats: EVENT_OBJECT_IME_SHOW/EVENT_OBJECT_IME_HIDE are supported on |
| 52 // Windows 8 and later. |
| 53 |
| 54 g_hook_handle_ = SetWinEventHook( |
| 55 EVENT_OBJECT_IME_SHOW, |
| 56 EVENT_OBJECT_IME_HIDE, |
| 57 NULL, |
| 58 ImeEventCallback, |
| 59 ::GetCurrentProcessId(), |
| 60 0, // Hook all threads because MS-IME emits WinEvent in worker thread |
| 61 WINEVENT_OUTOFCONTEXT); // allows us to receive message in the UI thread |
| 62 } |
| 63 |
| 64 void RemoveImePopupObserver(ImePopupObserver* observer) { |
| 65 if (g_observer_ != observer) |
| 66 return; |
| 67 g_observer_ = NULL; |
| 68 if (!g_hook_handle_) |
| 69 return; |
| 70 UnhookWinEvent(g_hook_handle_); |
| 71 g_hook_handle_ = NULL; |
| 72 } |
| 73 |
| 74 } // namespace metro_driver |
| 75 |
OLD | NEW |