summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ash/shell.cc3
-rw-r--r--content/shell/shell_stacking_client_ash.cc3
-rw-r--r--ui/base/ime/ime.gypi2
-rw-r--r--ui/base/ime/input_method.h1
-rw-r--r--ui/base/ime/input_method_base.cc3
-rw-r--r--ui/base/ime/input_method_factory.cc7
-rw-r--r--ui/base/ime/input_method_factory.h4
-rw-r--r--ui/base/ime/input_method_win.cc486
-rw-r--r--ui/base/ime/input_method_win.h119
-rw-r--r--ui/views/corewm/input_method_event_filter.cc4
-rw-r--r--ui/views/corewm/input_method_event_filter.h3
-rw-r--r--ui/views/corewm/input_method_event_filter_unittest.cc6
-rw-r--r--ui/views/ime/input_method_bridge.cc4
-rw-r--r--ui/views/ime/input_method_delegate.h1
-rw-r--r--ui/views/ime/input_method_win.cc11
-rw-r--r--ui/views/views.gyp2
-rw-r--r--ui/views/widget/desktop_aura/desktop_native_widget_aura.cc45
-rw-r--r--ui/views/widget/desktop_aura/desktop_native_widget_aura.h27
-rw-r--r--ui/views/widget/desktop_aura/desktop_root_window_host.h4
-rw-r--r--ui/views/widget/desktop_aura/desktop_root_window_host_linux.cc40
-rw-r--r--ui/views/widget/desktop_aura/desktop_root_window_host_linux.h16
-rw-r--r--ui/views/widget/desktop_aura/desktop_root_window_host_win.cc82
-rw-r--r--ui/views/widget/desktop_aura/desktop_root_window_host_win.h10
-rw-r--r--ui/views/widget/desktop_aura/desktop_stacking_client.cc3
-rw-r--r--ui/views/widget/native_widget_aura.cc14
-rw-r--r--ui/views/win/hwnd_message_handler.cc2
26 files changed, 740 insertions, 162 deletions
diff --git a/ash/shell.cc b/ash/shell.cc
index ffdcf99..5d8b830 100644
--- a/ash/shell.cc
+++ b/ash/shell.cc
@@ -474,7 +474,8 @@ void Shell::Init() {
AddPreTargetHandler(overlay_filter_.get());
AddShellObserver(overlay_filter_.get());
- input_method_filter_.reset(new views::corewm::InputMethodEventFilter);
+ input_method_filter_.reset(new views::corewm::InputMethodEventFilter(
+ root_window->GetAcceleratedWidget()));
AddPreTargetHandler(input_method_filter_.get());
#if !defined(OS_MACOSX)
diff --git a/content/shell/shell_stacking_client_ash.cc b/content/shell/shell_stacking_client_ash.cc
index a0b4f8d..f9e7c0a 100644
--- a/content/shell/shell_stacking_client_ash.cc
+++ b/content/shell/shell_stacking_client_ash.cc
@@ -38,7 +38,8 @@ aura::Window* ShellStackingClientAsh::GetDefaultParent(
// Pass ownership of the filter to the root_window.
root_window_->SetEventFilter(root_window_event_filter_);
- input_method_filter_.reset(new views::corewm::InputMethodEventFilter);
+ input_method_filter_.reset(new views::corewm::InputMethodEventFilter(
+ root_window_->GetAcceleratedWidget()));
input_method_filter_->SetInputMethodPropertyInRootWindow(
root_window_.get());
root_window_event_filter_->AddHandler(input_method_filter_.get());
diff --git a/ui/base/ime/ime.gypi b/ui/base/ime/ime.gypi
index f5eb297..2c71632 100644
--- a/ui/base/ime/ime.gypi
+++ b/ui/base/ime/ime.gypi
@@ -20,6 +20,8 @@
'input_method_factory.h',
'input_method_ibus.cc',
'input_method_ibus.h',
+ 'input_method_win.cc',
+ 'input_method_win.h',
'mock_input_method.cc',
'mock_input_method.h',
'text_input_client.cc',
diff --git a/ui/base/ime/input_method.h b/ui/base/ime/input_method.h
index c7d93cc..ae63be1 100644
--- a/ui/base/ime/input_method.h
+++ b/ui/base/ime/input_method.h
@@ -80,6 +80,7 @@ class InputMethod {
virtual void DispatchKeyEvent(const base::NativeEvent& native_key_event) = 0;
// TODO(yusukes): Add DispatchFabricatedKeyEvent to support virtual keyboards.
+ // TODO(yusukes): both win and ibus override to do nothing. Is this needed?
virtual void DispatchFabricatedKeyEvent(const ui::KeyEvent& event) = 0;
// Called by the focused client whenever its text input type is changed.
diff --git a/ui/base/ime/input_method_base.cc b/ui/base/ime/input_method_base.cc
index b6fa482..c1b094b 100644
--- a/ui/base/ime/input_method_base.cc
+++ b/ui/base/ime/input_method_base.cc
@@ -19,8 +19,7 @@ InputMethodBase::InputMethodBase()
InputMethodBase::~InputMethodBase() {
}
-void InputMethodBase::SetDelegate(
- internal::InputMethodDelegate* delegate) {
+void InputMethodBase::SetDelegate(internal::InputMethodDelegate* delegate) {
delegate_ = delegate;
}
diff --git a/ui/base/ime/input_method_factory.cc b/ui/base/ime/input_method_factory.cc
index 33f7698..5bb5be0 100644
--- a/ui/base/ime/input_method_factory.cc
+++ b/ui/base/ime/input_method_factory.cc
@@ -8,15 +8,20 @@
#if defined(OS_CHROMEOS)
#include "ui/base/ime/input_method_ibus.h"
+#elif defined(OS_WIN)
+#include "ui/base/ime/input_method_win.h"
#else
#include "ui/base/ime/mock_input_method.h"
#endif
namespace ui {
-InputMethod* CreateInputMethod(internal::InputMethodDelegate* delegate) {
+InputMethod* CreateInputMethod(internal::InputMethodDelegate* delegate,
+ gfx::AcceleratedWidget widget) {
#if defined(OS_CHROMEOS)
return new InputMethodIBus(delegate);
+#elif defined(OS_WIN)
+ return new InputMethodWin(delegate, widget);
#else
return new MockInputMethod(delegate);
#endif
diff --git a/ui/base/ime/input_method_factory.h b/ui/base/ime/input_method_factory.h
index 9bb81bc..db56bf74 100644
--- a/ui/base/ime/input_method_factory.h
+++ b/ui/base/ime/input_method_factory.h
@@ -6,6 +6,7 @@
#define UI_BASE_IME_INPUT_METHOD_FACTORY_H_
#include "ui/base/ui_export.h"
+#include "ui/gfx/native_widget_types.h"
namespace ui {
@@ -18,7 +19,8 @@ class InputMethodDelegate;
// Creates and returns an input method implementation for the platform. Caller
// must delete the object. The object does not own |delegate|.
UI_EXPORT InputMethod* CreateInputMethod(
- internal::InputMethodDelegate* delegate);
+ internal::InputMethodDelegate* delegate,
+ gfx::AcceleratedWidget widget);
} // namespace ui;
diff --git a/ui/base/ime/input_method_win.cc b/ui/base/ime/input_method_win.cc
new file mode 100644
index 0000000..3e6474e
--- /dev/null
+++ b/ui/base/ime/input_method_win.cc
@@ -0,0 +1,486 @@
+// Copyright (c) 2012 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 "ui/base/ime/input_method_win.h"
+
+#include "base/basictypes.h"
+#include "base/debug/stack_trace.h"
+#include "base/logging.h"
+#include "base/string_util.h"
+#include "ui/base/events/event.h"
+#include "ui/base/events/event_constants.h"
+#include "ui/base/events/event_utils.h"
+#include "ui/base/ime/composition_text.h"
+#include "ui/base/ime/input_method.h"
+#include "ui/base/ime/text_input_client.h"
+#include "ui/base/keycodes/keyboard_codes.h"
+
+// Extra number of chars before and after selection (or composition) range which
+// is returned to IME for improving conversion accuracy.
+static const size_t kExtraNumberOfChars = 20;
+
+namespace ui {
+
+InputMethodWin::InputMethodWin(internal::InputMethodDelegate* delegate,
+ HWND hwnd)
+ : hwnd_(hwnd),
+ active_(false),
+ direction_(base::i18n::UNKNOWN_DIRECTION),
+ pending_requested_direction_(base::i18n::UNKNOWN_DIRECTION),
+ enabled_(false) {
+ SetDelegate(delegate);
+}
+
+InputMethodWin::~InputMethodWin() {
+ ime_input_.DisableIME(hwnd_);
+}
+
+void InputMethodWin::Init(bool focused) {
+ // Gets the initial input locale and text direction information.
+ OnInputLangChange(0, 0);
+
+ InputMethodBase::Init(focused);
+}
+
+void InputMethodWin::OnFocus() {
+ InputMethodBase::OnFocus();
+ UpdateIMEState();
+}
+
+void InputMethodWin::OnBlur() {
+ ConfirmCompositionText();
+ InputMethodBase::OnBlur();
+}
+
+void InputMethodWin::DispatchKeyEvent(
+ const base::NativeEvent& native_key_event) {
+ if (native_key_event.message == WM_CHAR) {
+ BOOL handled;
+ OnChar(native_key_event.message, native_key_event.wParam,
+ native_key_event.lParam, &handled);
+ return; // Don't send WM_CHAR for post event processing.
+ }
+ // Handles ctrl-shift key to change text direction and layout alignment.
+ if (ui::ImeInput::IsRTLKeyboardLayoutInstalled() && !IsTextInputTypeNone()) {
+ // TODO: shouldn't need to generate a KeyEvent here.
+ const ui::KeyEvent key(native_key_event,
+ native_key_event.message == WM_CHAR);
+ ui::KeyboardCode code = key.key_code();
+ if (key.type() == ui::ET_KEY_PRESSED) {
+ if (code == ui::VKEY_SHIFT) {
+ base::i18n::TextDirection dir;
+ if (ui::ImeInput::IsCtrlShiftPressed(&dir))
+ pending_requested_direction_ = dir;
+ } else if (code != ui::VKEY_CONTROL) {
+ pending_requested_direction_ = base::i18n::UNKNOWN_DIRECTION;
+ }
+ } else if (key.type() == ui::ET_KEY_RELEASED &&
+ (code == ui::VKEY_SHIFT || code == ui::VKEY_CONTROL) &&
+ pending_requested_direction_ != base::i18n::UNKNOWN_DIRECTION) {
+ GetTextInputClient()->ChangeTextDirectionAndLayoutAlignment(
+ pending_requested_direction_);
+ pending_requested_direction_ = base::i18n::UNKNOWN_DIRECTION;
+ }
+ }
+
+ DispatchKeyEventPostIME(native_key_event);
+}
+
+void InputMethodWin::OnTextInputTypeChanged(const TextInputClient* client) {
+ if (IsTextInputClientFocused(client)) {
+ ime_input_.CancelIME(hwnd_);
+ UpdateIMEState();
+ }
+ InputMethodBase::OnTextInputTypeChanged(client);
+}
+
+void InputMethodWin::OnCaretBoundsChanged(const TextInputClient* client) {
+ if (!enabled_ || !IsTextInputClientFocused(client))
+ return;
+
+ // The current text input type should not be NONE if |client| is focused.
+ DCHECK(!IsTextInputTypeNone());
+ gfx::Rect screen_bounds(GetTextInputClient()->GetCaretBounds());
+ // TODO(ime): see comment in TextInputClient::GetCaretBounds(), this
+ // conversion shouldn't be necessary.
+ RECT r;
+ GetClientRect(hwnd_, &r);
+ POINT window_point = { screen_bounds.x(), screen_bounds.y() };
+ ScreenToClient(hwnd_, &window_point);
+ ime_input_.UpdateCaretRect(
+ hwnd_,
+ gfx::Rect(gfx::Point(window_point.x, window_point.y),
+ screen_bounds.size()));
+}
+
+void InputMethodWin::CancelComposition(const TextInputClient* client) {
+ if (enabled_ && IsTextInputClientFocused(client))
+ ime_input_.CancelIME(hwnd_);
+}
+
+std::string InputMethodWin::GetInputLocale() {
+ return locale_;
+}
+
+base::i18n::TextDirection InputMethodWin::GetInputTextDirection() {
+ return direction_;
+}
+
+bool InputMethodWin::IsActive() {
+ return active_;
+}
+
+LRESULT InputMethodWin::OnImeMessages(UINT message,
+ WPARAM w_param,
+ LPARAM l_param,
+ BOOL* handled) {
+ LRESULT result = 0;
+ switch (message) {
+ case WM_IME_SETCONTEXT:
+ result = OnImeSetContext(message, w_param, l_param, handled);
+ break;
+ case WM_IME_STARTCOMPOSITION:
+ result = OnImeStartComposition(message, w_param, l_param, handled);
+ break;
+ case WM_IME_COMPOSITION:
+ result = OnImeComposition(message, w_param, l_param, handled);
+ break;
+ case WM_IME_ENDCOMPOSITION:
+ result = OnImeEndComposition(message, w_param, l_param, handled);
+ break;
+ case WM_IME_REQUEST:
+ result = OnImeRequest(message, w_param, l_param, handled);
+ break;
+ case WM_CHAR:
+ case WM_SYSCHAR:
+ result = OnChar(message, w_param, l_param, handled);
+ break;
+ case WM_DEADCHAR:
+ case WM_SYSDEADCHAR:
+ result = OnDeadChar(message, w_param, l_param, handled);
+ break;
+ default:
+ NOTREACHED() << "Unknown IME message:" << message;
+ break;
+ }
+ return result;
+}
+
+void InputMethodWin::OnInputLangChange(DWORD character_set,
+ HKL input_language_id) {
+ active_ = ime_input_.SetInputLanguage();
+ locale_ = ime_input_.GetInputLanguageName();
+ direction_ = ime_input_.GetTextDirection();
+ OnInputMethodChanged();
+}
+
+void InputMethodWin::OnWillChangeFocusedClient(TextInputClient* focused_before,
+ TextInputClient* focused) {
+ ConfirmCompositionText();
+}
+
+void InputMethodWin::OnDidChangeFocusedClient(TextInputClient* focused_before,
+ TextInputClient* focused) {
+ // Force to update the input type since client's TextInputStateChanged()
+ // function might not be called if text input types before the client loses
+ // focus and after it acquires focus again are the same.
+ OnTextInputTypeChanged(focused);
+
+ UpdateIMEState();
+
+ // Force to update caret bounds, in case the client thinks that the caret
+ // bounds has not changed.
+ OnCaretBoundsChanged(focused);
+}
+
+LRESULT InputMethodWin::OnImeSetContext(UINT message,
+ WPARAM wparam,
+ LPARAM lparam,
+ BOOL* handled) {
+ active_ = (wparam == TRUE);
+ if (active_)
+ ime_input_.CreateImeWindow(hwnd_);
+
+ OnInputMethodChanged();
+ return ime_input_.SetImeWindowStyle(hwnd_, message, wparam, lparam, handled);
+}
+
+LRESULT InputMethodWin::OnImeStartComposition(UINT message,
+ WPARAM wparam,
+ LPARAM lparam,
+ BOOL* handled) {
+ // We have to prevent WTL from calling ::DefWindowProc() because the function
+ // calls ::ImmSetCompositionWindow() and ::ImmSetCandidateWindow() to
+ // over-write the position of IME windows.
+ *handled = TRUE;
+
+ if (IsTextInputTypeNone())
+ return 0;
+
+ // Reset the composition status and create IME windows.
+ ime_input_.CreateImeWindow(hwnd_);
+ ime_input_.ResetComposition(hwnd_);
+ return 0;
+}
+
+LRESULT InputMethodWin::OnImeComposition(UINT message,
+ WPARAM wparam,
+ LPARAM lparam,
+ BOOL* handled) {
+ // We have to prevent WTL from calling ::DefWindowProc() because we do not
+ // want for the IMM (Input Method Manager) to send WM_IME_CHAR messages.
+ *handled = TRUE;
+
+ if (IsTextInputTypeNone())
+ return 0;
+
+ // At first, update the position of the IME window.
+ ime_input_.UpdateImeWindow(hwnd_);
+
+ // Retrieve the result string and its attributes of the ongoing composition
+ // and send it to a renderer process.
+ ui::CompositionText composition;
+ if (ime_input_.GetResult(hwnd_, lparam, &composition.text)) {
+ GetTextInputClient()->InsertText(composition.text);
+ ime_input_.ResetComposition(hwnd_);
+ // Fall though and try reading the composition string.
+ // Japanese IMEs send a message containing both GCS_RESULTSTR and
+ // GCS_COMPSTR, which means an ongoing composition has been finished
+ // by the start of another composition.
+ }
+ // Retrieve the composition string and its attributes of the ongoing
+ // composition and send it to a renderer process.
+ if (ime_input_.GetComposition(hwnd_, lparam, &composition))
+ GetTextInputClient()->SetCompositionText(composition);
+
+ return 0;
+}
+
+LRESULT InputMethodWin::OnImeEndComposition(UINT message,
+ WPARAM wparam,
+ LPARAM lparam,
+ BOOL* handled) {
+ // Let WTL call ::DefWindowProc() and release its resources.
+ *handled = FALSE;
+
+ if (IsTextInputTypeNone())
+ return 0;
+
+ if (GetTextInputClient()->HasCompositionText())
+ GetTextInputClient()->ClearCompositionText();
+
+ ime_input_.ResetComposition(hwnd_);
+ ime_input_.DestroyImeWindow(hwnd_);
+ return 0;
+}
+
+LRESULT InputMethodWin::OnImeRequest(UINT message,
+ WPARAM wparam,
+ LPARAM lparam,
+ BOOL* handled) {
+ *handled = FALSE;
+
+ // Should not receive WM_IME_REQUEST message, if IME is disabled.
+ const ui::TextInputType type = GetTextInputType();
+ if (type == ui::TEXT_INPUT_TYPE_NONE ||
+ type == ui::TEXT_INPUT_TYPE_PASSWORD) {
+ return 0;
+ }
+
+ switch (wparam) {
+ case IMR_RECONVERTSTRING:
+ *handled = TRUE;
+ return OnReconvertString(reinterpret_cast<RECONVERTSTRING*>(lparam));
+ case IMR_DOCUMENTFEED:
+ *handled = TRUE;
+ return OnDocumentFeed(reinterpret_cast<RECONVERTSTRING*>(lparam));
+ default:
+ return 0;
+ }
+}
+
+LRESULT InputMethodWin::OnChar(UINT message,
+ WPARAM wparam,
+ LPARAM lparam,
+ BOOL* handled) {
+ *handled = TRUE;
+
+ // We need to send character events to the focused text input client event if
+ // its text input type is ui::TEXT_INPUT_TYPE_NONE.
+ if (!GetTextInputClient())
+ return 0;
+
+ GetTextInputClient()->InsertChar(static_cast<char16>(wparam),
+ ui::GetModifiersFromKeyState());
+ return 0;
+}
+
+LRESULT InputMethodWin::OnDeadChar(UINT message,
+ WPARAM wparam,
+ LPARAM lparam,
+ BOOL* handled) {
+ *handled = TRUE;
+
+ if (IsTextInputTypeNone())
+ return 0;
+
+ if (!GetTextInputClient())
+ return 0;
+
+ // Shows the dead character as a composition text, so that the user can know
+ // what dead key was pressed.
+ ui::CompositionText composition;
+ composition.text.assign(1, static_cast<char16>(wparam));
+ composition.selection = ui::Range(0, 1);
+ composition.underlines.push_back(
+ ui::CompositionUnderline(0, 1, SK_ColorBLACK, false));
+ GetTextInputClient()->SetCompositionText(composition);
+ return 0;
+}
+
+LRESULT InputMethodWin::OnDocumentFeed(RECONVERTSTRING* reconv) {
+ ui::TextInputClient* client = GetTextInputClient();
+ if (!client)
+ return 0;
+
+ ui::Range text_range;
+ if (!client->GetTextRange(&text_range) || text_range.is_empty())
+ return 0;
+
+ bool result = false;
+ ui::Range target_range;
+ if (client->HasCompositionText())
+ result = client->GetCompositionTextRange(&target_range);
+
+ if (!result || target_range.is_empty()) {
+ if (!client->GetSelectionRange(&target_range) ||
+ !target_range.IsValid()) {
+ return 0;
+ }
+ }
+
+ if (!text_range.Contains(target_range))
+ return 0;
+
+ if (target_range.GetMin() - text_range.start() > kExtraNumberOfChars)
+ text_range.set_start(target_range.GetMin() - kExtraNumberOfChars);
+
+ if (text_range.end() - target_range.GetMax() > kExtraNumberOfChars)
+ text_range.set_end(target_range.GetMax() + kExtraNumberOfChars);
+
+ size_t len = text_range.length();
+ size_t need_size = sizeof(RECONVERTSTRING) + len * sizeof(WCHAR);
+
+ if (!reconv)
+ return need_size;
+
+ if (reconv->dwSize < need_size)
+ return 0;
+
+ string16 text;
+ if (!GetTextInputClient()->GetTextFromRange(text_range, &text))
+ return 0;
+ DCHECK_EQ(text_range.length(), text.length());
+
+ reconv->dwVersion = 0;
+ reconv->dwStrLen = len;
+ reconv->dwStrOffset = sizeof(RECONVERTSTRING);
+ reconv->dwCompStrLen =
+ client->HasCompositionText() ? target_range.length() : 0;
+ reconv->dwCompStrOffset =
+ (target_range.GetMin() - text_range.start()) * sizeof(WCHAR);
+ reconv->dwTargetStrLen = target_range.length();
+ reconv->dwTargetStrOffset = reconv->dwCompStrOffset;
+
+ memcpy((char*)reconv + sizeof(RECONVERTSTRING),
+ text.c_str(), len * sizeof(WCHAR));
+
+ // According to Microsft API document, IMR_RECONVERTSTRING and
+ // IMR_DOCUMENTFEED should return reconv, but some applications return
+ // need_size.
+ return reinterpret_cast<LRESULT>(reconv);
+}
+
+LRESULT InputMethodWin::OnReconvertString(RECONVERTSTRING* reconv) {
+ ui::TextInputClient* client = GetTextInputClient();
+ if (!client)
+ return 0;
+
+ // If there is a composition string already, we don't allow reconversion.
+ if (client->HasCompositionText())
+ return 0;
+
+ ui::Range text_range;
+ if (!client->GetTextRange(&text_range) || text_range.is_empty())
+ return 0;
+
+ ui::Range selection_range;
+ if (!client->GetSelectionRange(&selection_range) ||
+ selection_range.is_empty()) {
+ return 0;
+ }
+
+ DCHECK(text_range.Contains(selection_range));
+
+ size_t len = selection_range.length();
+ size_t need_size = sizeof(RECONVERTSTRING) + len * sizeof(WCHAR);
+
+ if (!reconv)
+ return need_size;
+
+ if (reconv->dwSize < need_size)
+ return 0;
+
+ // TODO(penghuang): Return some extra context to help improve IME's
+ // reconversion accuracy.
+ string16 text;
+ if (!GetTextInputClient()->GetTextFromRange(selection_range, &text))
+ return 0;
+ DCHECK_EQ(selection_range.length(), text.length());
+
+ reconv->dwVersion = 0;
+ reconv->dwStrLen = len;
+ reconv->dwStrOffset = sizeof(RECONVERTSTRING);
+ reconv->dwCompStrLen = len;
+ reconv->dwCompStrOffset = 0;
+ reconv->dwTargetStrLen = len;
+ reconv->dwTargetStrOffset = 0;
+
+ memcpy(reinterpret_cast<char*>(reconv) + sizeof(RECONVERTSTRING),
+ text.c_str(), len * sizeof(WCHAR));
+
+ // According to Microsft API document, IMR_RECONVERTSTRING and
+ // IMR_DOCUMENTFEED should return reconv, but some applications return
+ // need_size.
+ return reinterpret_cast<LRESULT>(reconv);
+}
+
+void InputMethodWin::ConfirmCompositionText() {
+ if (!IsTextInputTypeNone()) {
+ ime_input_.CleanupComposition(hwnd_);
+ // Though above line should confirm the client's composition text by sending
+ // a result text to us, in case the input method and the client are in
+ // inconsistent states, we check the client's composition state again.
+ if (GetTextInputClient()->HasCompositionText())
+ GetTextInputClient()->ConfirmCompositionText();
+ }
+}
+
+void InputMethodWin::UpdateIMEState() {
+ // Use switch here in case we are going to add more text input types.
+ // We disable input method in password field.
+ switch (GetTextInputType()) {
+ case ui::TEXT_INPUT_TYPE_NONE:
+ case ui::TEXT_INPUT_TYPE_PASSWORD:
+ ime_input_.DisableIME(hwnd_);
+ enabled_ = false;
+ break;
+ default:
+ ime_input_.EnableIME(hwnd_);
+ enabled_ = true;
+ break;
+ }
+}
+
+} // namespace ui
diff --git a/ui/base/ime/input_method_win.h b/ui/base/ime/input_method_win.h
new file mode 100644
index 0000000..414b490
--- /dev/null
+++ b/ui/base/ime/input_method_win.h
@@ -0,0 +1,119 @@
+// Copyright (c) 2011 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 UI_BASE_IME_INPUT_METHOD_WIN_H_
+#define UI_BASE_IME_INPUT_METHOD_WIN_H_
+
+#include <windows.h>
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "ui/base/ime/input_method_base.h"
+#include "ui/base/win/ime_input.h"
+
+namespace ui {
+
+// An InputMethod implementation based on Windows IMM32 API.
+class UI_EXPORT InputMethodWin : public InputMethodBase {
+ public:
+ explicit InputMethodWin(internal::InputMethodDelegate* delegate, HWND hwnd);
+ virtual ~InputMethodWin();
+
+ // Overridden from InputMethod:
+ virtual void Init(bool focused) OVERRIDE;
+ virtual void OnFocus() OVERRIDE;
+ virtual void OnBlur() OVERRIDE;
+ virtual void DispatchKeyEvent(
+ const base::NativeEvent& native_key_event) OVERRIDE;
+ virtual void DispatchFabricatedKeyEvent(const ui::KeyEvent& event) OVERRIDE {}
+ virtual void OnTextInputTypeChanged(const TextInputClient* client) OVERRIDE;
+ virtual void OnCaretBoundsChanged(const TextInputClient* client) OVERRIDE;
+ virtual void CancelComposition(const TextInputClient* client) OVERRIDE;
+ virtual std::string GetInputLocale() OVERRIDE;
+ virtual base::i18n::TextDirection GetInputTextDirection() OVERRIDE;
+ virtual bool IsActive() OVERRIDE;
+
+ // Handles IME messages.
+ LRESULT OnImeMessages(UINT message,
+ WPARAM wparam,
+ LPARAM lparam,
+ BOOL* handled);
+
+ // Message handlers. The native widget is responsible for forwarding following
+ // messages to the input method.
+ void OnInputLangChange(DWORD character_set, HKL input_language_id);
+
+ protected:
+ // Overridden from InputMethodBase:
+ virtual void OnWillChangeFocusedClient(TextInputClient* focused_before,
+ TextInputClient* focused) OVERRIDE;
+ virtual void OnDidChangeFocusedClient(TextInputClient* focused_before,
+ TextInputClient* focused) OVERRIDE;
+
+ private:
+ LRESULT OnImeSetContext(UINT message,
+ WPARAM wparam,
+ LPARAM lparam,
+ BOOL* handled);
+ LRESULT OnImeStartComposition(UINT message,
+ WPARAM wparam,
+ LPARAM lparam,
+ BOOL* handled);
+ LRESULT OnImeComposition(UINT message,
+ WPARAM wparam,
+ LPARAM lparam,
+ BOOL* handled);
+ LRESULT OnImeEndComposition(UINT message,
+ WPARAM wparam,
+ LPARAM lparam,
+ BOOL* handled);
+ LRESULT OnImeRequest(UINT message,
+ WPARAM wparam,
+ LPARAM lparam,
+ BOOL* handled);
+ // For both WM_CHAR and WM_SYSCHAR
+ LRESULT OnChar(UINT message, WPARAM wparam, LPARAM lparam, BOOL* handled);
+ // For both WM_DEADCHAR and WM_SYSDEADCHAR
+ LRESULT OnDeadChar(UINT message, WPARAM wparam, LPARAM lparam, BOOL* handled);
+
+ LRESULT OnDocumentFeed(RECONVERTSTRING *reconv);
+ LRESULT OnReconvertString(RECONVERTSTRING *reconv);
+
+ // Asks the client to confirm current composition text.
+ void ConfirmCompositionText();
+
+ // Enables or disables the IME according to the current text input type.
+ void UpdateIMEState();
+
+ // The HWND this InputMethod is bound to.
+ HWND hwnd_;
+
+ // Indicates if the current input locale has an IME.
+ bool active_;
+
+ // Name of the current input locale.
+ std::string locale_;
+
+ // The current input text direction.
+ base::i18n::TextDirection direction_;
+
+ // The new text direction and layout alignment requested by the user by
+ // pressing ctrl-shift. It'll be sent to the text input client when the key
+ // is released.
+ base::i18n::TextDirection pending_requested_direction_;
+
+ // Windows IMM32 wrapper.
+ // (See "ui/base/win/ime_input.h" for its details.)
+ ui::ImeInput ime_input_;
+
+ bool enabled_;
+
+ DISALLOW_COPY_AND_ASSIGN(InputMethodWin);
+};
+
+} // namespace ui
+
+#endif // UI_BASE_IME_INPUT_METHOD_WIN_H_
diff --git a/ui/views/corewm/input_method_event_filter.cc b/ui/views/corewm/input_method_event_filter.cc
index 350ab4f..f80d3ca 100644
--- a/ui/views/corewm/input_method_event_filter.cc
+++ b/ui/views/corewm/input_method_event_filter.cc
@@ -16,9 +16,9 @@ namespace corewm {
////////////////////////////////////////////////////////////////////////////////
// InputMethodEventFilter, public:
-InputMethodEventFilter::InputMethodEventFilter()
+InputMethodEventFilter::InputMethodEventFilter(gfx::AcceleratedWidget widget)
: ALLOW_THIS_IN_INITIALIZER_LIST(
- input_method_(ui::CreateInputMethod(this))),
+ input_method_(ui::CreateInputMethod(this, widget))),
target_root_window_(NULL) {
// TODO(yusukes): Check if the root window is currently focused and pass the
// result to Init().
diff --git a/ui/views/corewm/input_method_event_filter.h b/ui/views/corewm/input_method_event_filter.h
index 99a42c3..c0d3a94 100644
--- a/ui/views/corewm/input_method_event_filter.h
+++ b/ui/views/corewm/input_method_event_filter.h
@@ -10,6 +10,7 @@
#include "base/memory/scoped_ptr.h"
#include "ui/base/events/event_handler.h"
#include "ui/base/ime/input_method_delegate.h"
+#include "ui/gfx/native_widget_types.h"
#include "ui/views/views_export.h"
namespace aura {
@@ -29,7 +30,7 @@ class VIEWS_EXPORT InputMethodEventFilter
: public ui::EventHandler,
public ui::internal::InputMethodDelegate {
public:
- InputMethodEventFilter();
+ explicit InputMethodEventFilter(gfx::AcceleratedWidget widget);
virtual ~InputMethodEventFilter();
void SetInputMethodPropertyInRootWindow(aura::RootWindow* root_window);
diff --git a/ui/views/corewm/input_method_event_filter_unittest.cc b/ui/views/corewm/input_method_event_filter_unittest.cc
index c4e7b5a..a5927ab 100644
--- a/ui/views/corewm/input_method_event_filter_unittest.cc
+++ b/ui/views/corewm/input_method_event_filter_unittest.cc
@@ -32,7 +32,8 @@ TEST_F(InputMethodEventFilterTest, TestInputMethodProperty) {
CompoundEventFilter* root_filter = new CompoundEventFilter;
root_window()->SetEventFilter(root_filter);
- InputMethodEventFilter input_method_event_filter;
+ InputMethodEventFilter input_method_event_filter(
+ root_window()->GetAcceleratedWidget());
root_filter->AddHandler(&input_method_event_filter);
// Tests if InputMethodEventFilter adds a window property on its
@@ -50,7 +51,8 @@ TEST_F(InputMethodEventFilterTest, TestInputMethodKeyEventPropagation) {
root_window()->SetEventFilter(root_filter);
// Add the InputMethodEventFilter before the TestEventFilter.
- InputMethodEventFilter input_method_event_filter;
+ InputMethodEventFilter input_method_event_filter(
+ root_window()->GetAcceleratedWidget());
root_filter->AddHandler(&input_method_event_filter);
// Add TestEventFilter to the RootWindow.
diff --git a/ui/views/ime/input_method_bridge.cc b/ui/views/ime/input_method_bridge.cc
index 438e3308..58b5f84 100644
--- a/ui/views/ime/input_method_bridge.cc
+++ b/ui/views/ime/input_method_bridge.cc
@@ -43,7 +43,9 @@ void InputMethodBridge::OnFocus() {
}
void InputMethodBridge::OnBlur() {
- DCHECK(widget_focused());
+ // win32 sends multiple focus lost events, ignore all but the first.
+ if (widget_focused())
+ return;
ConfirmCompositionText();
InputMethodBase::OnBlur();
diff --git a/ui/views/ime/input_method_delegate.h b/ui/views/ime/input_method_delegate.h
index f2a2479..59bc9dc 100644
--- a/ui/views/ime/input_method_delegate.h
+++ b/ui/views/ime/input_method_delegate.h
@@ -23,7 +23,6 @@ class VIEWS_EXPORT InputMethodDelegate {
// Dispatch a key event already processed by the input method.
virtual void DispatchKeyEventPostIME(const ui::KeyEvent& key) = 0;
-
};
} // namespace internal
diff --git a/ui/views/ime/input_method_win.cc b/ui/views/ime/input_method_win.cc
index f29bceb..d7b15cf 100644
--- a/ui/views/ime/input_method_win.cc
+++ b/ui/views/ime/input_method_win.cc
@@ -45,24 +45,13 @@ void InputMethodWin::Init(Widget* widget) {
}
void InputMethodWin::OnFocus() {
-#if !defined(USE_AURA)
- // On Aura, there are different ways of getting here (HWNDMessageHandler and
- // FocusManager) and since they don't know about the focus state that each
- // other is in, this DCHECK comes up.
- // TODO(ime): ifdefing this out is a hack, the root problem needs to be
- // addressed.
DCHECK(!widget_focused());
-#endif
InputMethodBase::OnFocus();
UpdateIMEState();
}
void InputMethodWin::OnBlur() {
-#if !defined(USE_AURA)
- // TODO(ime): ifdefing this out is a hack, the root problem needs to be
- // addressed.
DCHECK(widget_focused());
-#endif
ConfirmCompositionText();
InputMethodBase::OnBlur();
}
diff --git a/ui/views/views.gyp b/ui/views/views.gyp
index 2d82e32..edc77d6 100644
--- a/ui/views/views.gyp
+++ b/ui/views/views.gyp
@@ -473,8 +473,6 @@
}],
['OS=="win"', {
'sources/': [
- ['include', 'ime/input_method_win.cc'],
- ['include', 'ime/input_method_win.h'],
['include', 'widget/desktop_aura/desktop_screen_win.cc'],
['include', 'widget/desktop_aura/desktop_screen_win.h'],
['include', 'widget/desktop_aura/desktop_root_window_host_win.cc'],
diff --git a/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc b/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
index b03b41e..0a11531 100644
--- a/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
+++ b/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
@@ -15,7 +15,10 @@
#include "ui/compositor/layer.h"
#include "ui/gfx/canvas.h"
#include "ui/native_theme/native_theme.h"
+#include "ui/views/corewm/compound_event_filter.h"
+#include "ui/views/corewm/input_method_event_filter.h"
#include "ui/views/ime/input_method.h"
+#include "ui/views/ime/input_method_bridge.h"
#include "ui/views/widget/desktop_aura/desktop_root_window_host.h"
#include "ui/views/widget/native_widget_aura_window_observer.h"
#include "ui/views/widget/widget.h"
@@ -85,11 +88,30 @@ DesktopNativeWidgetAura* DesktopNativeWidgetAura::ForWindow(
}
void DesktopNativeWidgetAura::OnHostClosed() {
+ root_window_event_filter_->RemoveHandler(input_method_event_filter_.get());
// This will, through a long list of callbacks, trigger |root_window_| going
// away. See OnWindowDestroyed()
delete window_;
}
+void DesktopNativeWidgetAura::InstallInputMethodEventFilter(
+ aura::RootWindow* root) {
+ DCHECK(!input_method_event_filter_.get());
+
+ // CEF sets focus to the window the user clicks down on.
+ // TODO(beng): see if we can't do this some other way. CEF seems a heavy-
+ // handed way of accomplishing focus.
+ // No event filter for aura::Env. Create CompoundEvnetFilter per RootWindow.
+ root_window_event_filter_ = new corewm::CompoundEventFilter;
+ // Pass ownership of the filter to the root_window.
+ root->SetEventFilter(root_window_event_filter_);
+
+ input_method_event_filter_.reset(
+ new corewm::InputMethodEventFilter(root->GetAcceleratedWidget()));
+ input_method_event_filter_->SetInputMethodPropertyInRootWindow(root);
+ root_window_event_filter_->AddHandler(input_method_event_filter_.get());
+}
+
////////////////////////////////////////////////////////////////////////////////
// DesktopNativeWidgetAura, internal::NativeWidgetPrivate implementation:
@@ -208,12 +230,13 @@ bool DesktopNativeWidgetAura::HasCapture() const {
}
InputMethod* DesktopNativeWidgetAura::CreateInputMethod() {
- return desktop_root_window_host_->CreateInputMethod();
+ ui::InputMethod* host = input_method_event_filter_->input_method();
+ return new InputMethodBridge(this, host);
}
internal::InputMethodDelegate*
DesktopNativeWidgetAura::GetInputMethodDelegate() {
- return desktop_root_window_host_->GetInputMethodDelegate();
+ return this;
}
void DesktopNativeWidgetAura::CenterWindow(const gfx::Size& size) {
@@ -445,6 +468,13 @@ void DesktopNativeWidgetAura::OnBoundsChanged(const gfx::Rect& old_bounds,
void DesktopNativeWidgetAura::OnFocus(aura::Window* old_focused_window) {
desktop_root_window_host_->OnNativeWidgetFocus();
native_widget_delegate_->OnNativeFocus(old_focused_window);
+
+ // If focus is moving from a descendant Window to |window_| then native
+ // activation hasn't changed. We still need to inform the InputMethod we've
+ // been focused though.
+ InputMethod* input_method = GetWidget()->GetInputMethod();
+ if (input_method)
+ input_method->OnFocus();
}
void DesktopNativeWidgetAura::OnBlur() {
@@ -592,4 +622,15 @@ void DesktopNativeWidgetAura::OnLostActive() {
GetWidget()->non_client_view()->SchedulePaint();
}
+////////////////////////////////////////////////////////////////////////////////
+// DesktopNativeWidgetAura, views::internal::InputMethodDelegate:
+
+void DesktopNativeWidgetAura::DispatchKeyEventPostIME(const ui::KeyEvent& key) {
+ FocusManager* focus_manager =
+ native_widget_delegate_->AsWidget()->GetFocusManager();
+ if (native_widget_delegate_->OnKeyEvent(key) || !focus_manager)
+ return;
+ focus_manager->OnKeyEvent(key);
+}
+
} // namespace views
diff --git a/ui/views/widget/desktop_aura/desktop_native_widget_aura.h b/ui/views/widget/desktop_aura/desktop_native_widget_aura.h
index b3abe0f..63977a5 100644
--- a/ui/views/widget/desktop_aura/desktop_native_widget_aura.h
+++ b/ui/views/widget/desktop_aura/desktop_native_widget_aura.h
@@ -8,6 +8,7 @@
#include "base/memory/weak_ptr.h"
#include "ui/aura/client/activation_delegate.h"
#include "ui/aura/window_delegate.h"
+#include "ui/views/ime/input_method_delegate.h"
#include "ui/views/widget/native_widget_private.h"
namespace aura {
@@ -19,6 +20,11 @@ class StackingClient;
namespace views {
+namespace corewm {
+class CompoundEventFilter;
+class InputMethodEventFilter;
+}
+
class DesktopRootWindowHost;
class NativeWidgetAuraWindowObserver;
@@ -26,7 +32,8 @@ class NativeWidgetAuraWindowObserver;
class VIEWS_EXPORT DesktopNativeWidgetAura
: public internal::NativeWidgetPrivate,
public aura::WindowDelegate,
- public aura::client::ActivationDelegate {
+ public aura::client::ActivationDelegate,
+ public views::internal::InputMethodDelegate {
public:
explicit DesktopNativeWidgetAura(internal::NativeWidgetDelegate* delegate);
virtual ~DesktopNativeWidgetAura();
@@ -38,6 +45,16 @@ class VIEWS_EXPORT DesktopNativeWidgetAura
// this is the signal that we should start our shutdown.
void OnHostClosed();
+ // Installs the input method filter on |root|. This is intended to be invoked
+ // by the DesktopRootWindowHost implementation during Init().
+ void InstallInputMethodEventFilter(aura::RootWindow* root);
+ corewm::InputMethodEventFilter* input_method_event_filter() {
+ return input_method_event_filter_.get();
+ }
+ corewm::CompoundEventFilter* root_window_event_filter() {
+ return root_window_event_filter_;
+ }
+
protected:
// Overridden from internal::NativeWidgetPrivate:
virtual void InitNativeWidget(const Widget::InitParams& params) OVERRIDE;
@@ -160,6 +177,9 @@ class VIEWS_EXPORT DesktopNativeWidgetAura
virtual void OnActivated() OVERRIDE;
virtual void OnLostActive() OVERRIDE;
+ // Overridden from views::internal::InputMethodDelegate:
+ virtual void DispatchKeyEventPostIME(const ui::KeyEvent& key) OVERRIDE;
+
private:
// See class documentation for Widget in widget.h for a note about ownership.
Widget::InitParams::Ownership ownership_;
@@ -184,6 +204,11 @@ class VIEWS_EXPORT DesktopNativeWidgetAura
scoped_ptr<aura::client::StackingClient> stacking_client_;
+ // Toplevel event filter which dispatches to other event filters.
+ corewm::CompoundEventFilter* root_window_event_filter_;
+
+ scoped_ptr<corewm::InputMethodEventFilter> input_method_event_filter_;
+
DISALLOW_COPY_AND_ASSIGN(DesktopNativeWidgetAura);
};
diff --git a/ui/views/widget/desktop_aura/desktop_root_window_host.h b/ui/views/widget/desktop_aura/desktop_root_window_host.h
index bf2655e..b8066e5 100644
--- a/ui/views/widget/desktop_aura/desktop_root_window_host.h
+++ b/ui/views/widget/desktop_aura/desktop_root_window_host.h
@@ -26,7 +26,6 @@ class NativeTheme;
namespace views {
class DesktopNativeWidgetAura;
namespace internal {
-class InputMethodDelegate;
class NativeWidgetDelegate;
}
@@ -82,9 +81,6 @@ class VIEWS_EXPORT DesktopRootWindowHost {
virtual void SetAlwaysOnTop(bool always_on_top) = 0;
- virtual InputMethod* CreateInputMethod() = 0;
- virtual internal::InputMethodDelegate* GetInputMethodDelegate() = 0;
-
virtual void SetWindowTitle(const string16& title) = 0;
virtual void ClearNativeFocus() = 0;
diff --git a/ui/views/widget/desktop_aura/desktop_root_window_host_linux.cc b/ui/views/widget/desktop_aura/desktop_root_window_host_linux.cc
index eab034ca..3d75f77 100644
--- a/ui/views/widget/desktop_aura/desktop_root_window_host_linux.cc
+++ b/ui/views/widget/desktop_aura/desktop_root_window_host_linux.cc
@@ -22,8 +22,6 @@
#include "ui/base/x/x11_util.h"
#include "ui/native_theme/native_theme.h"
#include "ui/views/corewm/compound_event_filter.h"
-#include "ui/views/corewm/input_method_event_filter.h"
-#include "ui/views/ime/input_method_bridge.h"
#include "ui/views/widget/desktop_aura/desktop_activation_client.h"
#include "ui/views/widget/desktop_aura/desktop_cursor_client.h"
#include "ui/views/widget/desktop_aura/desktop_dispatcher_client.h"
@@ -231,20 +229,14 @@ aura::RootWindow* DesktopRootWindowHostLinux::InitRootWindow(
aura::client::SetScreenPositionClient(root_window_,
position_client_.get());
- // No event filter for aura::Env. Create CompoundEvnetFilter per RootWindow.
- root_window_event_filter_ = new corewm::CompoundEventFilter;
- // Pass ownership of the filter to the root_window.
- root_window_->SetEventFilter(root_window_event_filter_);
-
- input_method_filter_.reset(new corewm::InputMethodEventFilter);
- input_method_filter_->SetInputMethodPropertyInRootWindow(root_window_);
- root_window_event_filter_->AddHandler(input_method_filter_.get());
+ desktop_native_widget_aura_->InstallInputMethodEventFilter(root_window_);
// TODO(erg): Unify this code once the other consumer goes away.
x11_window_event_filter_.reset(
new X11WindowEventFilter(root_window_, activation_client_.get()));
x11_window_event_filter_->SetUseHostWindowBorders(false);
- root_window_event_filter_->AddHandler(x11_window_event_filter_.get());
+ desktop_native_widget_aura_->root_window_event_filter()->AddHandler(
+ x11_window_event_filter_.get());
x11_window_move_client_.reset(new X11DesktopWindowMoveClient);
aura::client::SetWindowMoveClient(root_window_,
@@ -328,8 +320,8 @@ void DesktopRootWindowHostLinux::Close() {
void DesktopRootWindowHostLinux::CloseNow() {
// Remove the event listeners we've installed. We need to remove these
// because otherwise we get assert during ~RootWindow().
- root_window_event_filter_->RemoveHandler(x11_window_event_filter_.get());
- root_window_event_filter_->RemoveHandler(input_method_filter_.get());
+ desktop_native_widget_aura_->root_window_event_filter()->RemoveHandler(
+ x11_window_event_filter_.get());
// Actually free our native resources.
base::MessagePumpAuraX11::Current()->RemoveDispatcherForWindow(xwindow_);
@@ -512,16 +504,6 @@ void DesktopRootWindowHostLinux::SetAlwaysOnTop(bool always_on_top) {
NOTIMPLEMENTED();
}
-InputMethod* DesktopRootWindowHostLinux::CreateInputMethod() {
- ui::InputMethod* host = input_method_filter_->input_method();
- return new InputMethodBridge(this, host);
-}
-
-internal::InputMethodDelegate*
- DesktopRootWindowHostLinux::GetInputMethodDelegate() {
- return this;
-}
-
void DesktopRootWindowHostLinux::SetWindowTitle(const string16& title) {
XStoreName(xdisplay_, xwindow_, UTF16ToUTF8(title).c_str());
}
@@ -846,18 +828,6 @@ void DesktopRootWindowHostLinux::PrepareForShutdown() {
}
////////////////////////////////////////////////////////////////////////////////
-// DesktopRootWindowHostLinux, views::internal::InputMethodDelegate:
-
-void DesktopRootWindowHostLinux::DispatchKeyEventPostIME(
- const ui::KeyEvent& key) {
- FocusManager* focus_manager =
- native_widget_delegate_->AsWidget()->GetFocusManager();
- if (native_widget_delegate_->OnKeyEvent(key) || !focus_manager)
- return;
- focus_manager->OnKeyEvent(key);
-}
-
-////////////////////////////////////////////////////////////////////////////////
// DesktopRootWindowHostLinux, MessageLoop::Dispatcher implementation:
bool DesktopRootWindowHostLinux::Dispatch(const base::NativeEvent& event) {
diff --git a/ui/views/widget/desktop_aura/desktop_root_window_host_linux.h b/ui/views/widget/desktop_aura/desktop_root_window_host_linux.h
index e8748f5..ae5b736d 100644
--- a/ui/views/widget/desktop_aura/desktop_root_window_host_linux.h
+++ b/ui/views/widget/desktop_aura/desktop_root_window_host_linux.h
@@ -17,7 +17,6 @@
#include "ui/gfx/rect.h"
#include "ui/base/cursor/cursor_loader_x11.h"
#include "ui/base/x/x11_atom_cache.h"
-#include "ui/views/ime/input_method_delegate.h"
#include "ui/views/views_export.h"
#include "ui/views/widget/desktop_aura/desktop_root_window_host.h"
@@ -35,15 +34,10 @@ class DesktopCursorClient;
class DesktopDispatcherClient;
class X11DesktopWindowMoveClient;
class X11WindowEventFilter;
-namespace corewm {
-class CompoundEventFilter;
-class InputMethodEventFilter;
-}
class VIEWS_EXPORT DesktopRootWindowHostLinux
: public DesktopRootWindowHost,
public aura::RootWindowHost,
- public views::internal::InputMethodDelegate,
public MessageLoop::Dispatcher {
public:
DesktopRootWindowHostLinux(
@@ -122,8 +116,6 @@ class VIEWS_EXPORT DesktopRootWindowHostLinux
virtual bool IsMinimized() const OVERRIDE;
virtual bool HasCapture() const OVERRIDE;
virtual void SetAlwaysOnTop(bool always_on_top) OVERRIDE;
- virtual InputMethod* CreateInputMethod() OVERRIDE;
- virtual internal::InputMethodDelegate* GetInputMethodDelegate() OVERRIDE;
virtual void SetWindowTitle(const string16& title) OVERRIDE;
virtual void ClearNativeFocus() OVERRIDE;
virtual Widget::MoveLoopResult RunMoveLoop(
@@ -174,9 +166,6 @@ class VIEWS_EXPORT DesktopRootWindowHostLinux
virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE;
virtual void PrepareForShutdown() OVERRIDE;
- // Overridden from views::internal::InputMethodDelegate:
- virtual void DispatchKeyEventPostIME(const ui::KeyEvent& key) OVERRIDE;
-
// Overridden from Dispatcher:
virtual bool Dispatch(const base::NativeEvent& event) OVERRIDE;
@@ -221,11 +210,6 @@ class VIEWS_EXPORT DesktopRootWindowHostLinux
// The invisible cursor.
::Cursor invisible_cursor_;
- // Toplevel event filter which dispatches to other event filters.
- corewm::CompoundEventFilter* root_window_event_filter_;
-
- // An event filter that pre-handles all key events to send them to an IME.
- scoped_ptr<corewm::InputMethodEventFilter> input_method_filter_;
scoped_ptr<X11WindowEventFilter> x11_window_event_filter_;
scoped_ptr<X11DesktopWindowMoveClient> x11_window_move_client_;
diff --git a/ui/views/widget/desktop_aura/desktop_root_window_host_win.cc b/ui/views/widget/desktop_aura/desktop_root_window_host_win.cc
index 3fdaef7..ce4c73b 100644
--- a/ui/views/widget/desktop_aura/desktop_root_window_host_win.cc
+++ b/ui/views/widget/desktop_aura/desktop_root_window_host_win.cc
@@ -13,6 +13,7 @@
#include "ui/aura/ui_controls_aura.h"
#include "ui/aura/window_property.h"
#include "ui/base/cursor/cursor_loader_win.h"
+#include "ui/base/ime/input_method_win.h"
#include "ui/base/win/shell.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/path_win.h"
@@ -21,7 +22,7 @@
#include "ui/ui_controls/ui_controls.h"
#include "ui/views/corewm/compound_event_filter.h"
#include "ui/views/corewm/input_method_event_filter.h"
-#include "ui/views/ime/input_method_win.h"
+#include "ui/views/ime/input_method_bridge.h"
#include "ui/views/widget/desktop_aura/desktop_activation_client.h"
#include "ui/views/widget/desktop_aura/desktop_cursor_client.h"
#include "ui/views/widget/desktop_aura/desktop_dispatcher_client.h"
@@ -134,15 +135,7 @@ aura::RootWindow* DesktopRootWindowHostWin::Init(
aura::client::SetScreenPositionClient(root_window_,
position_client_.get());
- // CEF sets focus to the window the user clicks down on.
- // TODO(beng): see if we can't do this some other way. CEF seems a heavy-
- // handed way of accomplishing focus.
- root_window_event_filter_ = new views::corewm::CompoundEventFilter;
- root_window_->SetEventFilter(root_window_event_filter_);
-
- input_method_filter_.reset(new views::corewm::InputMethodEventFilter);
- input_method_filter_->SetInputMethodPropertyInRootWindow(root_window_);
- root_window_event_filter_->AddHandler(input_method_filter_.get());
+ desktop_native_widget_aura_->InstallInputMethodEventFilter(root_window_);
focus_client_->FocusWindow(content_window_, NULL);
root_window_->SetProperty(kContentWindowForRootWindow, content_window_);
@@ -258,25 +251,6 @@ void DesktopRootWindowHostWin::SetAlwaysOnTop(bool always_on_top) {
message_handler_->SetAlwaysOnTop(always_on_top);
}
-InputMethod* DesktopRootWindowHostWin::CreateInputMethod() {
- // TODO(ime): This is wrong. We need to hook up the native win32 IME on the
- // InputMethodEventFilter, and instead create an InputMethodBridge
- // per-NativeWidget implementation. Once we achieve that we can get rid of
- // this function on this object and DesktopRootWindowHostLinux and just
- // create the InputMethodBridge directly in DesktopNativeWidgetAura. Also
- // at that time DNWA can become the InputMethodDelegate.
- ui::InputMethod* host =
- root_window_->GetProperty(aura::client::kRootWindowInputMethodKey);
- return new InputMethodWin(message_handler_.get(),
- message_handler_->hwnd(),
- host);
-}
-
-internal::InputMethodDelegate*
- DesktopRootWindowHostWin::GetInputMethodDelegate() {
- return message_handler_.get();
-}
-
void DesktopRootWindowHostWin::SetWindowTitle(const string16& title) {
message_handler_->SetTitle(title);
}
@@ -623,7 +597,6 @@ void DesktopRootWindowHostWin::HandleDestroying() {
}
void DesktopRootWindowHostWin::HandleDestroyed() {
- root_window_event_filter_->RemoveHandler(input_method_filter_.get());
desktop_native_widget_aura_->OnHostClosed();
}
@@ -692,29 +665,35 @@ bool DesktopRootWindowHostWin::HandleMouseEvent(const ui::MouseEvent& event) {
}
bool DesktopRootWindowHostWin::HandleKeyEvent(const ui::KeyEvent& event) {
- return root_window_host_delegate_->OnHostKeyEvent(
- const_cast<ui::KeyEvent*>(&event));
+ // We must return false here so HWNDMessageHandler::DispatchKeyEventPostIME()
+ // marks the message as not handled. This enables win32 to map things like an
+ // alt key press to a WM_SYSCHAR for showing a menu.
+ // NOTE: we get here because HandleIMEMessage() below returns false. We need
+ // not do anything as HandleIMEMessage already processed the message.
+ return false;
}
bool DesktopRootWindowHostWin::HandleUntranslatedKeyEvent(
const ui::KeyEvent& event) {
- InputMethod* input_method = GetInputMethod();
- if (input_method)
- input_method->DispatchKeyEvent(event);
- return !!input_method;
+ scoped_ptr<ui::KeyEvent> duplicate_event(event.Copy());
+ static_cast<aura::RootWindowHostDelegate*>(root_window_)->OnHostKeyEvent(
+ duplicate_event.get());
+ // We must return false here so that HWNDMessageHandler invokes
+ // HandleKeyEvent(). See comment in HandleKeyEvent as to why it's important.
+ return false;
}
bool DesktopRootWindowHostWin::HandleIMEMessage(UINT message,
- WPARAM w_param,
- LPARAM l_param,
- LRESULT* result) {
- InputMethod* input_method = GetInputMethod();
- if (!input_method || input_method->IsMock()) {
- *result = 0;
- return false;
- }
-
- InputMethodWin* ime_win = static_cast<InputMethodWin*>(input_method);
+ WPARAM w_param,
+ LPARAM l_param,
+ LRESULT* result) {
+ // TODO(ime): Having to cast here is wrong. Maybe we should have IME events
+ // and have these flow through the same path as HandleUntranslatedKeyEvent()
+ // does.
+ ui::InputMethodWin* ime_win =
+ static_cast<ui::InputMethodWin*>(
+ desktop_native_widget_aura_->input_method_event_filter()->
+ input_method());
BOOL handled = FALSE;
*result = ime_win->OnImeMessages(message, w_param, l_param, &handled);
return !!handled;
@@ -723,11 +702,12 @@ bool DesktopRootWindowHostWin::HandleIMEMessage(UINT message,
void DesktopRootWindowHostWin::HandleInputLanguageChange(
DWORD character_set,
HKL input_language_id) {
- InputMethod* input_method = GetInputMethod();
- if (input_method && !input_method->IsMock()) {
- static_cast<InputMethodWin*>(input_method)->OnInputLangChange(
- character_set, input_language_id);
- }
+ // TODO(ime): Seem comment in HandleIMEMessage().
+ ui::InputMethodWin* ime_win =
+ static_cast<ui::InputMethodWin*>(
+ desktop_native_widget_aura_->input_method_event_filter()->
+ input_method());
+ ime_win->OnInputLangChange(character_set, input_language_id);
}
bool DesktopRootWindowHostWin::HandlePaintAccelerated(
diff --git a/ui/views/widget/desktop_aura/desktop_root_window_host_win.h b/ui/views/widget/desktop_aura/desktop_root_window_host_win.h
index 927123b..8ff793c 100644
--- a/ui/views/widget/desktop_aura/desktop_root_window_host_win.h
+++ b/ui/views/widget/desktop_aura/desktop_root_window_host_win.h
@@ -23,10 +23,6 @@ class DesktopActivationClient;
class DesktopCursorClient;
class DesktopDispatcherClient;
class HWNDMessageHandler;
-namespace corewm {
-class CompoundEventFilter;
-class InputMethodEventFilter;
-}
class VIEWS_EXPORT DesktopRootWindowHostWin
: public DesktopRootWindowHost,
@@ -73,8 +69,6 @@ class VIEWS_EXPORT DesktopRootWindowHostWin
virtual bool IsMinimized() const OVERRIDE;
virtual bool HasCapture() const OVERRIDE;
virtual void SetAlwaysOnTop(bool always_on_top) OVERRIDE;
- virtual InputMethod* CreateInputMethod() OVERRIDE;
- virtual internal::InputMethodDelegate* GetInputMethodDelegate() OVERRIDE;
virtual void SetWindowTitle(const string16& title) OVERRIDE;
virtual void ClearNativeFocus() OVERRIDE;
virtual Widget::MoveLoopResult RunMoveLoop(
@@ -213,7 +207,6 @@ class VIEWS_EXPORT DesktopRootWindowHostWin
scoped_ptr<aura::client::FocusClient> focus_client_;
// Depends on focus_manager_.
scoped_ptr<DesktopActivationClient> activation_client_;
- scoped_ptr<corewm::InputMethodEventFilter> input_method_filter_;
// TODO(beng): Consider providing an interface to DesktopNativeWidgetAura
// instead of providing this route back to Widget.
@@ -231,9 +224,6 @@ class VIEWS_EXPORT DesktopRootWindowHostWin
// A simple cursor client which just forwards events to the RootWindow.
scoped_ptr<DesktopCursorClient> cursor_client_;
- // The RootWindow's CompoundEventFilter.
- views::corewm::CompoundEventFilter* root_window_event_filter_;
-
DISALLOW_COPY_AND_ASSIGN(DesktopRootWindowHostWin);
};
diff --git a/ui/views/widget/desktop_aura/desktop_stacking_client.cc b/ui/views/widget/desktop_aura/desktop_stacking_client.cc
index 46ffe9c..e26f478 100644
--- a/ui/views/widget/desktop_aura/desktop_stacking_client.cc
+++ b/ui/views/widget/desktop_aura/desktop_stacking_client.cc
@@ -49,7 +49,8 @@ void DesktopStackingClient::CreateNULLParent() {
window_event_filter_ = new corewm::CompoundEventFilter;
null_parent_->SetEventFilter(window_event_filter_);
- input_method_filter_.reset(new corewm::InputMethodEventFilter);
+ input_method_filter_.reset(new corewm::InputMethodEventFilter(
+ null_parent_->GetAcceleratedWidget()));
input_method_filter_->SetInputMethodPropertyInRootWindow(null_parent_.get());
window_event_filter_->AddHandler(input_method_filter_.get());
diff --git a/ui/views/widget/native_widget_aura.cc b/ui/views/widget/native_widget_aura.cc
index 31548af..e11da64 100644
--- a/ui/views/widget/native_widget_aura.cc
+++ b/ui/views/widget/native_widget_aura.cc
@@ -800,20 +800,6 @@ ui::EventResult NativeWidgetAura::OnKeyEvent(ui::KeyEvent* event) {
// and the window may be invisible by that time.
if (!window_->IsVisible())
return ui::ER_UNHANDLED;
-#if defined(OS_WIN)
- // Work around for incomplete InputMethod wiring. If we're in a constrained
- // window DispatchKeyEvent below results in an infinite loop. Short circuit
- // that by invoking DispatchKeyEventIME() directly, which is what
- // InputMethodBridge::DispatchKeyEvent does.
- // TODO(ime): remove this hack.
- if (DesktopRootWindowHostWin::GetContentWindowForHWND(
- window_->GetRootWindow()->GetAcceleratedWidget()) &&
- (event->type() != ui::ET_TRANSLATED_KEY_PRESS &&
- event->type() != ui::ET_TRANSLATED_KEY_RELEASE)) {
- DispatchKeyEventPostIME(*event);
- return ui::ER_HANDLED;
- }
-#endif
GetWidget()->GetInputMethod()->DispatchKeyEvent(*event);
return ui::ER_HANDLED;
}
diff --git a/ui/views/win/hwnd_message_handler.cc b/ui/views/win/hwnd_message_handler.cc
index 91718e7..57cbfaf 100644
--- a/ui/views/win/hwnd_message_handler.cc
+++ b/ui/views/win/hwnd_message_handler.cc
@@ -463,7 +463,6 @@ gfx::Rect HWNDMessageHandler::GetClientAreaBoundsInScreen() const {
return gfx::Rect(point.x, point.y, r.right - r.left, r.bottom - r.top);
}
-
gfx::Rect HWNDMessageHandler::GetRestoredBounds() const {
// If we're in fullscreen mode, we've changed the normal bounds to the monitor
// rect, so return the saved bounds instead.
@@ -1436,7 +1435,6 @@ void HWNDMessageHandler::OnInputLangChange(DWORD character_set,
LRESULT HWNDMessageHandler::OnKeyEvent(UINT message,
WPARAM w_param,
LPARAM l_param) {
-
MSG msg = { hwnd(), message, w_param, l_param };
ui::KeyEvent key(msg, message == WM_CHAR);
if (!delegate_->HandleUntranslatedKeyEvent(key))