Index: views/widget/widget_win.cc |
diff --git a/views/widget/widget_win.cc b/views/widget/widget_win.cc |
index 0d6f47c548494383ccd6749925c19084f1d04621..1cadfb1d341e7560da24912716e5250fe86d5866 100644 |
--- a/views/widget/widget_win.cc |
+++ b/views/widget/widget_win.cc |
@@ -23,9 +23,11 @@ |
#include "ui/gfx/path.h" |
#include "views/accessibility/native_view_accessibility_win.h" |
#include "views/controls/native_control_win.h" |
+#include "views/controls/textfield/native_textfield_views.h" |
#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" |
@@ -143,11 +145,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(); |
} |
@@ -333,6 +339,19 @@ bool WidgetWin::HasMouseCapture() 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); |
@@ -383,6 +402,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 |
@@ -620,6 +644,15 @@ 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() && |
+ NativeTextfieldViews::IsTextfieldViewsEnabled()) { |
+ input_method_.reset(new InputMethodWin(this)); |
+ input_method_->Init(GetWidget()); |
+ is_input_method_win_ = true; |
+ } |
return 0; |
} |
@@ -699,6 +732,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); |
} |
@@ -709,28 +781,37 @@ 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 = { hwnd(), 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 = { hwnd(), 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 (input_method_.get()) |
+ input_method_->OnBlur(); |
SetMsgHandled(FALSE); |
} |
@@ -863,6 +944,8 @@ LRESULT WidgetWin::OnReflectedMessage(UINT msg, |
void WidgetWin::OnSetFocus(HWND focused_window) { |
delegate_->OnNativeFocus(focused_window); |
+ if (input_method_.get()) |
+ input_method_->OnFocus(); |
SetMsgHandled(FALSE); |
} |
@@ -1057,6 +1140,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: |