Index: win8/metro_driver/chrome_app_view_ash.cc |
diff --git a/win8/metro_driver/chrome_app_view_ash.cc b/win8/metro_driver/chrome_app_view_ash.cc |
index 3eae110957c1aed375eb469c1be09e0a8ddd0d23..428ef4fef4b1eb8e8addfbe7a619ccf47c885676 100644 |
--- a/win8/metro_driver/chrome_app_view_ash.cc |
+++ b/win8/metro_driver/chrome_app_view_ash.cc |
@@ -24,6 +24,10 @@ |
#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/keyevent_filter.h" |
+#include "win8/metro_driver/ime/language_profile_monitor.h" |
+#include "win8/metro_driver/ime/text_service.h" |
#include "win8/metro_driver/metro_driver.h" |
#include "win8/metro_driver/winrt_utils.h" |
#include "win8/viewer/metro_viewer_constants.h" |
@@ -164,6 +168,10 @@ class ChromeChannelListener : public IPC::Listener { |
IPC_MESSAGE_HANDLER(MetroViewerHostMsg_DisplaySelectFolder, |
OnDisplayFolderPicker) |
IPC_MESSAGE_HANDLER(MetroViewerHostMsg_SetCursorPos, OnSetCursorPos) |
+ IPC_MESSAGE_HANDLER(MetroViewerHostMsg_ImeCancelComposition, |
+ OnImeCancelComposition) |
+ IPC_MESSAGE_HANDLER(MetroViewerHostMsg_ImeTextInputClientUpdated, |
+ OnImeTextInputClientChanged) |
IPC_MESSAGE_UNHANDLED(__debugbreak()) |
IPC_END_MESSAGE_MAP() |
return true; |
@@ -241,6 +249,23 @@ class ChromeChannelListener : public IPC::Listener { |
x, y)); |
} |
+ void OnImeCancelComposition() { |
+ ui_proxy_->PostTask( |
+ FROM_HERE, |
+ base::Bind(&ChromeAppViewAsh::OnImeCancelComposition, |
+ base::Unretained(app_view_))); |
+ } |
+ |
+ void OnImeTextInputClientChanged( |
+ const std::vector<int32>& input_scopes, |
+ const std::vector<metro_viewer::CharacterBounds>& character_bounds) { |
+ ui_proxy_->PostTask( |
+ FROM_HERE, |
+ base::Bind(&ChromeAppViewAsh::OnImeUpdateTextInputClient, |
+ base::Unretained(app_view_), |
+ input_scopes, |
+ character_bounds)); |
+ } |
scoped_refptr<base::MessageLoopProxy> ui_proxy_; |
ChromeAppViewAsh* app_view_; |
@@ -435,11 +460,17 @@ bool LaunchChromeBrowserProcess(const wchar_t* additional_parameters, |
} // namespace |
+struct ChromeAppViewAsh::TextInputClientState { |
+ std::vector<int32> input_scopes; |
+ std::vector<metro_viewer::CharacterBounds> composition_character_bounds; |
+}; |
+ |
ChromeAppViewAsh::ChromeAppViewAsh() |
: mouse_down_flags_(ui::EF_NONE), |
ui_channel_(nullptr), |
core_window_hwnd_(NULL), |
- ui_loop_(base::MessageLoop::TYPE_UI) { |
+ ui_loop_(base::MessageLoop::TYPE_UI), |
+ text_input_client_state_(new TextInputClientState) { |
DVLOG(1) << __FUNCTION__; |
globals.previous_state = |
winapp::Activation::ApplicationExecutionState_NotRunning; |
@@ -457,6 +488,8 @@ ChromeAppViewAsh::Initialize(winapp::Core::ICoreApplicationView* view) { |
this, &ChromeAppViewAsh::OnActivate).Get(), |
&activated_token_); |
CheckHR(hr); |
+ if (!metro_driver::InstallKeyEventFilter()) |
+ return E_FAIL; |
return hr; |
} |
@@ -472,6 +505,10 @@ ChromeAppViewAsh::SetWindow(winui::Core::ICoreWindow* window) { |
hr = interop->get_WindowHandle(&core_window_hwnd_); |
CheckHR(hr); |
+ text_service_.reset(new metro_driver::TextService(core_window_hwnd_, this)); |
+ metro_driver::AddImePopupObserver(this); |
+ metro_driver::AddLanguageProfileObserver(this); |
+ |
hr = window_->add_SizeChanged(mswr::Callback<SizeChangedHandler>( |
this, &ChromeAppViewAsh::OnSizeChanged).Get(), |
&sizechange_token_); |
@@ -619,6 +656,9 @@ ChromeAppViewAsh::Run() { |
IFACEMETHODIMP |
ChromeAppViewAsh::Uninitialize() { |
DVLOG(1) << __FUNCTION__; |
+ metro_driver::UninstallKeyEventFilter(); |
+ metro_driver::RemoveImePopupObserver(this); |
+ metro_driver::RemoveLanguageProfileObserver(this); |
window_ = nullptr; |
view_ = nullptr; |
core_window_hwnd_ = NULL; |
@@ -787,6 +827,76 @@ void ChromeAppViewAsh::OnFolderPickerCompleted( |
delete folder_picker; |
} |
+void ChromeAppViewAsh::OnImeCancelComposition() { |
+ text_service_->CancelComposition(); |
+} |
+ |
+void ChromeAppViewAsh::OnImeUpdateTextInputClient( |
+ const std::vector<int32>& input_scopes, |
+ const std::vector<metro_viewer::CharacterBounds>& character_bounds) { |
+ if (text_input_client_state_->input_scopes != input_scopes) { |
+ text_service_->OnDocumentTypeChanged(input_scopes); |
+ text_input_client_state_->input_scopes = input_scopes; |
+ } |
+ text_input_client_state_->composition_character_bounds = character_bounds; |
+} |
+ |
+void ChromeAppViewAsh::OnCandidatePopupChanged(bool shown) { |
+ ui_channel_->Send(new MetroViewerHostMsg_ImeCandidatePopupChanged(shown)); |
+} |
+ |
+void ChromeAppViewAsh::OnInputSourceChanged(LANGID langid, bool is_ime) { |
+ ui_channel_->Send(new MetroViewerHostMsg_ImeInputSourceChanged( |
+ langid, is_ime)); |
+} |
+ |
+void ChromeAppViewAsh::OnCompositionChanged( |
+ const string16& text, |
+ int32 selection_start, |
+ int32 selection_end, |
+ const std::vector<metro_viewer::UnderlineInfo>& underlines) { |
+ ui_channel_->Send(new MetroViewerHostMsg_ImeCompositionChanged( |
+ text, selection_start, selection_end, underlines)); |
+} |
+ |
+void ChromeAppViewAsh::OnTextCommitted(const string16& text) { |
+ ui_channel_->Send(new MetroViewerHostMsg_ImeTextCommitted(text)); |
+} |
+ |
+RECT ChromeAppViewAsh::GetCaretBounds() { |
+ if (text_input_client_state_->composition_character_bounds.empty()) { |
+ const RECT rect = {}; |
+ return rect; |
+ } |
+ const metro_viewer::CharacterBounds& bounds = |
+ text_input_client_state_->composition_character_bounds[0]; |
+ POINT left_top = {bounds.left, bounds.top}; |
+ POINT right_bottom = {bounds.right, bounds.bottom}; |
+ ::ClientToScreen(this->core_window_hwnd_, &left_top); |
+ ::ClientToScreen(this->core_window_hwnd_, &right_bottom); |
+ const RECT rect = { |
+ left_top.x, |
+ left_top.y, |
+ right_bottom.x, |
+ right_bottom.y, |
+ }; |
+ return rect; |
+} |
+ |
+bool ChromeAppViewAsh::GetCompositionCharacterBounds(uint32 index, RECT* rect) { |
+ if (index >= text_input_client_state_->composition_character_bounds.size()) { |
+ return false; |
+ } |
+ const metro_viewer::CharacterBounds& bounds = |
+ text_input_client_state_->composition_character_bounds[index]; |
+ POINT left_top = {bounds.left, bounds.top}; |
+ POINT right_bottom = {bounds.right, bounds.bottom}; |
+ ::ClientToScreen(this->core_window_hwnd_, &left_top); |
+ ::ClientToScreen(this->core_window_hwnd_, &right_bottom); |
+ ::SetRect(rect, left_top.x, left_top.y, right_bottom.x, right_bottom.y); |
+ return true; |
+} |
+ |
HRESULT ChromeAppViewAsh::OnActivate( |
winapp::Core::ICoreApplicationView*, |
winapp::Activation::IActivatedEventArgs* args) { |
@@ -1033,6 +1143,12 @@ HRESULT ChromeAppViewAsh::OnWindowActivated( |
// clicked back in Ash after using another app on another monitor) the same. |
if (state == winui::Core::CoreWindowActivationState_CodeActivated || |
state == winui::Core::CoreWindowActivationState_PointerActivated) { |
+ switch (state) { |
+ case winui::Core::CoreWindowActivationState_CodeActivated: |
+ case winui::Core::CoreWindowActivationState_PointerActivated: |
+ text_service_->OnWindowActivated(); |
+ break; |
+ } |
ui_channel_->Send(new MetroViewerHostMsg_WindowActivated()); |
} |
return S_OK; |