Index: views/widget/widget_win.cc |
diff --git a/views/widget/widget_win.cc b/views/widget/widget_win.cc |
index 6badb94790e8444fe8b3720faf663264d6bdf869..03420d99509d87decc875991031d015f2cadbe41 100644 |
--- a/views/widget/widget_win.cc |
+++ b/views/widget/widget_win.cc |
@@ -26,6 +26,7 @@ |
#include "views/focus/accelerator_handler.h" |
#include "views/focus/focus_util_win.h" |
#include "views/focus/view_storage.h" |
+#include "views/ime/input_method_win.h" |
#include "views/views_delegate.h" |
#include "views/widget/aero_tooltip_manager.h" |
#include "views/widget/child_window_message_processor.h" |
@@ -145,11 +146,15 @@ WidgetWin::WidgetWin() |
restore_focus_when_enabled_(false), |
accessibility_view_events_index_(-1), |
accessibility_view_events_(kMaxAccessibilityViewEvents), |
- previous_cursor_(NULL) { |
+ previous_cursor_(NULL), |
+ is_input_method_win_(false) { |
set_native_widget(this); |
} |
WidgetWin::~WidgetWin() { |
+ // We need to delete the input method before calling DestroyRootView(), |
+ // because it'll set focus_manager_ to NULL. |
+ input_method_.reset(); |
DestroyRootView(); |
} |
@@ -332,6 +337,19 @@ bool WidgetWin::HasNativeCapture() const { |
return GetCapture() == hwnd(); |
} |
+InputMethod* WidgetWin::GetInputMethodNative() { |
+ return input_method_.get(); |
+} |
+ |
+void WidgetWin::ReplaceInputMethod(InputMethod* input_method) { |
+ input_method_.reset(input_method); |
+ if (input_method) { |
+ input_method->set_delegate(this); |
+ input_method->Init(GetWidget()); |
+ } |
+ is_input_method_win_ = false; |
+} |
+ |
gfx::Rect WidgetWin::GetWindowScreenBounds() const { |
RECT r; |
GetWindowRect(&r); |
@@ -382,6 +400,11 @@ void WidgetWin::Close() { |
} |
void WidgetWin::CloseNow() { |
+ // Destroys the input method before closing the window so that it can be |
+ // detached from the widget correctly. |
+ input_method_.reset(); |
+ is_input_method_win_ = false; |
+ |
// We may already have been destroyed if the selection resulted in a tab |
// switch which will have reactivated the browser window and closed us, so |
// we need to check to see if we're still a window before trying to destroy |
@@ -621,6 +644,14 @@ LRESULT WidgetWin::OnCreate(CREATESTRUCT* create_struct) { |
ClientAreaSizeChanged(); |
delegate_->OnNativeWidgetCreated(); |
+ |
+ // delegate_->OnNativeWidgetCreated() creates the focus manager for top-level |
+ // widget. Only top-level widget should have an input method. |
+ if (delegate_->HasFocusManager()) { |
+ input_method_.reset(new InputMethodWin(this)); |
+ input_method_->Init(GetWidget()); |
+ is_input_method_win_ = true; |
+ } |
return 0; |
} |
@@ -700,6 +731,45 @@ void WidgetWin::OnHScroll(int scroll_type, short position, HWND scrollbar) { |
SetMsgHandled(FALSE); |
} |
+LRESULT WidgetWin::OnImeMessages(UINT message, WPARAM w_param, LPARAM l_param) { |
+ if (!is_input_method_win_) { |
+ SetMsgHandled(FALSE); |
+ return 0; |
+ } |
+ |
+ InputMethodWin* ime = static_cast<InputMethodWin*>(input_method_.get()); |
+ BOOL handled = FALSE; |
+ LRESULT result = 0; |
+ switch (message) { |
+ case WM_IME_SETCONTEXT: |
+ result = ime->OnImeSetContext(message, w_param, l_param, &handled); |
+ break; |
+ case WM_IME_STARTCOMPOSITION: |
+ result = ime->OnImeStartComposition(message, w_param, l_param, &handled); |
+ break; |
+ case WM_IME_COMPOSITION: |
+ result = ime->OnImeComposition(message, w_param, l_param, &handled); |
+ break; |
+ case WM_IME_ENDCOMPOSITION: |
+ result = ime->OnImeEndComposition(message, w_param, l_param, &handled); |
+ break; |
+ case WM_CHAR: |
+ case WM_SYSCHAR: |
+ result = ime->OnChar(message, w_param, l_param, &handled); |
+ break; |
+ case WM_DEADCHAR: |
+ case WM_SYSDEADCHAR: |
+ result = ime->OnDeadChar(message, w_param, l_param, &handled); |
+ break; |
+ default: |
+ NOTREACHED() << "Unknown IME message:" << message; |
+ break; |
+ } |
+ |
+ SetMsgHandled(handled); |
+ return result; |
+} |
+ |
void WidgetWin::OnInitMenu(HMENU menu) { |
SetMsgHandled(FALSE); |
} |
@@ -710,30 +780,39 @@ void WidgetWin::OnInitMenuPopup(HMENU menu, |
SetMsgHandled(FALSE); |
} |
-LRESULT WidgetWin::OnKeyDown(UINT message, WPARAM w_param, LPARAM l_param) { |
- RootView* root_view = GetFocusedViewRootView(); |
- if (!root_view) |
- root_view = GetRootView(); |
+void WidgetWin::OnInputLangChange(DWORD character_set, HKL input_language_id) { |
+ if (is_input_method_win_) { |
+ static_cast<InputMethodWin*>(input_method_.get())->OnInputLangChange( |
+ character_set, input_language_id); |
+ } |
+} |
+LRESULT WidgetWin::OnKeyDown(UINT message, WPARAM w_param, LPARAM l_param) { |
MSG msg; |
MakeMSG(&msg, message, w_param, l_param); |
- SetMsgHandled(root_view->ProcessKeyEvent(KeyEvent(msg))); |
+ KeyEvent key(msg); |
+ if (input_method_.get()) |
+ input_method_->DispatchKeyEvent(key); |
+ else |
+ DispatchKeyEventPostIME(key); |
return 0; |
} |
LRESULT WidgetWin::OnKeyUp(UINT message, WPARAM w_param, LPARAM l_param) { |
- RootView* root_view = GetFocusedViewRootView(); |
- if (!root_view) |
- root_view = GetRootView(); |
- |
MSG msg; |
MakeMSG(&msg, message, w_param, l_param); |
- SetMsgHandled(root_view->ProcessKeyEvent(KeyEvent(msg))); |
+ KeyEvent key(msg); |
+ if (input_method_.get()) |
+ input_method_->DispatchKeyEvent(key); |
+ else |
+ DispatchKeyEventPostIME(key); |
return 0; |
} |
void WidgetWin::OnKillFocus(HWND focused_window) { |
delegate_->OnNativeBlur(focused_window); |
+ if (is_input_method_win_) |
+ static_cast<InputMethodWin*>(input_method_.get())->OnKillFocus(); |
SetMsgHandled(FALSE); |
} |
@@ -911,6 +990,8 @@ LRESULT WidgetWin::OnReflectedMessage(UINT msg, |
void WidgetWin::OnSetFocus(HWND focused_window) { |
delegate_->OnNativeFocus(focused_window); |
+ if (is_input_method_win_) |
+ static_cast<InputMethodWin*>(input_method_.get())->OnSetFocus(); |
SetMsgHandled(FALSE); |
} |
@@ -1193,6 +1274,14 @@ gfx::AcceleratedWidget WidgetWin::GetAcceleratedWidget() { |
return gfx::kNullAcceleratedWidget; |
} |
+void WidgetWin::DispatchKeyEventPostIME(const KeyEvent& key) { |
+ RootView* root_view = GetFocusedViewRootView(); |
+ if (!root_view) |
+ root_view = GetRootView(); |
+ |
+ SetMsgHandled(root_view->ProcessKeyEvent(key)); |
+} |
+ |
//////////////////////////////////////////////////////////////////////////////// |
// Widget, public: |