| Index: chrome/browser/renderer_host/render_widget_host_view_views.cc
|
| diff --git a/chrome/browser/renderer_host/render_widget_host_view_views.cc b/chrome/browser/renderer_host/render_widget_host_view_views.cc
|
| index 5e90c81ae61b5e5d4bb86991acfc7784cfa23606..9db5bbb5d400730a8f84c9995ccece589a68c1d6 100644
|
| --- a/chrome/browser/renderer_host/render_widget_host_view_views.cc
|
| +++ b/chrome/browser/renderer_host/render_widget_host_view_views.cc
|
| @@ -26,6 +26,7 @@
|
| #include "ui/base/x/x11_util.h"
|
| #include "ui/gfx/canvas.h"
|
| #include "views/events/event.h"
|
| +#include "views/ime/ime_context.h"
|
| #include "views/widget/widget.h"
|
| #include "views/widget/widget_gtk.h"
|
|
|
| @@ -33,6 +34,20 @@ static const int kMaxWindowWidth = 4000;
|
| static const int kMaxWindowHeight = 4000;
|
| static const char* kRenderWidgetHostViewKey = "__RENDER_WIDGET_HOST_VIEW__";
|
|
|
| +// Copied from third_party/WebKit/Source/WebCore/page/EventHandler.cpp
|
| +//
|
| +// Match key code of composition keydown event on windows.
|
| +// IE sends VK_PROCESSKEY which has value 229;
|
| +//
|
| +// Please refer to following documents for detals:
|
| +// - Virtual-Key Codes
|
| +// http://msdn.microsoft.com/en-us/library/ms645540(VS.85).aspx
|
| +// - How the IME System Works
|
| +// http://msdn.microsoft.com/en-us/library/cc194848.aspx
|
| +// - ImmGetVirtualKey Function
|
| +// http://msdn.microsoft.com/en-us/library/dd318570(VS.85).aspx
|
| +static const int kCompositionEventKeyCode = 229;
|
| +
|
| using WebKit::WebInputEventFactory;
|
| using WebKit::WebMouseWheelEvent;
|
| using WebKit::WebTouchEvent;
|
| @@ -113,6 +128,149 @@ void InitializeWebMouseEventFromViewsEvent(const views::LocatedEvent& e,
|
|
|
| } // namespace
|
|
|
| +class IMEContextHandler : public views::CommitTextListener,
|
| + public views::CompositionListener,
|
| + public views::ForwardKeyEventListener {
|
| + public:
|
| + explicit IMEContextHandler(
|
| + RenderWidgetHostViewViews* host_view)
|
| + : host_view_(host_view),
|
| + is_enabled_(false),
|
| + is_focused_(false),
|
| + ime_context_(views::IMEContext::Create(host_view_)) {
|
| + ime_context_->set_commit_text_listener(this);
|
| + ime_context_->set_composition_listener(this);
|
| + ime_context_->set_forward_key_event_listener(this);
|
| + }
|
| +
|
| + // IMEContext Listeners implementation
|
| + virtual void OnCommitText(views::IMEContext* sender,
|
| + const string16& text) {
|
| + DCHECK(ime_context_ == sender);
|
| +
|
| + RenderWidgetHost* host = host_view_->GetRenderWidgetHost();
|
| + if (host) {
|
| + SendFakeCompositionWebKeyboardEvent(WebKit::WebInputEvent::RawKeyDown);
|
| + host->ImeConfirmComposition(text);
|
| + SendFakeCompositionWebKeyboardEvent(WebKit::WebInputEvent::KeyUp);
|
| + }
|
| + }
|
| +
|
| + virtual void OnStartComposition(views::IMEContext* sender) {
|
| + DCHECK(ime_context_ == sender);
|
| + }
|
| +
|
| + virtual void OnEndComposition(views::IMEContext* sender) {
|
| + DCHECK(ime_context_ == sender);
|
| +
|
| + RenderWidgetHost* host = host_view_->GetRenderWidgetHost();
|
| + if (host)
|
| + host->ImeCancelComposition();
|
| + }
|
| +
|
| + virtual void OnSetComposition(views::IMEContext* sender,
|
| + const string16& text,
|
| + const views::CompositionAttributeList& attributes,
|
| + uint32 cursor_pos) {
|
| + DCHECK(ime_context_ == sender);
|
| +
|
| + RenderWidgetHost* host = host_view_->GetRenderWidgetHost();
|
| + if (host) {
|
| + SendFakeCompositionWebKeyboardEvent(WebKit::WebInputEvent::RawKeyDown);
|
| +
|
| + // Cast CompositonAttribute to WebKit::WebCompositionUnderline directly,
|
| + // becasue CompositionAttribute is duplicated from
|
| + // WebKit::WebCompositionUnderline.
|
| + const std::vector<WebKit::WebCompositionUnderline>& underlines =
|
| + reinterpret_cast<const std::vector<WebKit::WebCompositionUnderline>&>(
|
| + attributes);
|
| + host->ImeSetComposition(text, underlines, cursor_pos, cursor_pos);
|
| + SendFakeCompositionWebKeyboardEvent(WebKit::WebInputEvent::KeyUp);
|
| + }
|
| + }
|
| +
|
| + virtual void OnForwardKeyEvent(views::IMEContext* sender,
|
| + const views::KeyEvent& event) {
|
| + DCHECK(ime_context_ == sender);
|
| +
|
| + host_view_->ForwardKeyEvent(event);
|
| + }
|
| +
|
| + bool FilterKeyEvent(const views::KeyEvent& event) {
|
| + return is_enabled_ && ime_context_->FilterKeyEvent(event);
|
| + }
|
| +
|
| + void Focus() {
|
| + if (!is_focused_) {
|
| + ime_context_->Focus();
|
| + is_focused_ = true;
|
| + }
|
| +
|
| + // Enables RenderWidget's IME related events, so that we can be notified
|
| + // when WebKit wants to enable or disable IME.
|
| + RenderWidgetHost* host = host_view_->GetRenderWidgetHost();
|
| + if (host)
|
| + host->SetInputMethodActive(true);
|
| + }
|
| +
|
| + void Blur() {
|
| + if (is_focused_) {
|
| + ime_context_->Blur();
|
| + is_focused_ = false;
|
| + }
|
| +
|
| + // Disable RenderWidget's IME related events to save bandwidth.
|
| + RenderWidgetHost* host = host_view_->GetRenderWidgetHost();
|
| + if (host)
|
| + host->SetInputMethodActive(false);
|
| + }
|
| +
|
| + void ImeUpdateTextInputState(WebKit::WebTextInputType type,
|
| + const gfx::Rect& caret_rect) {
|
| + bool enable =
|
| + (type != WebKit::WebTextInputTypeNone) &&
|
| + (type != WebKit::WebTextInputTypePassword);
|
| +
|
| + if (is_enabled_ != enable) {
|
| + is_enabled_ = enable;
|
| + if (is_focused_) {
|
| + if (is_enabled_)
|
| + ime_context_->Focus();
|
| + else
|
| + ime_context_->Blur();
|
| + }
|
| + }
|
| +
|
| + if (is_enabled_) {
|
| + gfx::Point p(caret_rect.origin());
|
| + views::View::ConvertPointToScreen(host_view_, &p);
|
| +
|
| + ime_context_->SetCursorLocation(gfx::Rect(p, caret_rect.size()));
|
| + }
|
| + }
|
| +
|
| + void Reset() {
|
| + ime_context_->Reset();
|
| + }
|
| +
|
| + private:
|
| + void SendFakeCompositionWebKeyboardEvent(WebKit::WebInputEvent::Type type) {
|
| + NativeWebKeyboardEvent fake_event;
|
| + fake_event.windowsKeyCode = kCompositionEventKeyCode;
|
| + fake_event.skip_in_browser = true;
|
| + fake_event.type = type;
|
| + host_view_->ForwardWebKeyboardEvent(fake_event);
|
| + }
|
| +
|
| + private:
|
| + RenderWidgetHostViewViews* host_view_;
|
| + bool is_enabled_;
|
| + bool is_focused_;
|
| + scoped_ptr<views::IMEContext> ime_context_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(IMEContextHandler);
|
| +};
|
| +
|
| // static
|
| RenderWidgetHostView* RenderWidgetHostView::CreateViewForWidget(
|
| RenderWidgetHost* widget) {
|
| @@ -137,6 +295,7 @@ RenderWidgetHostViewViews::~RenderWidgetHostViewViews() {
|
|
|
| void RenderWidgetHostViewViews::InitAsChild() {
|
| Show();
|
| + ime_context_.reset(new IMEContextHandler(this));
|
| }
|
|
|
| RenderWidgetHost* RenderWidgetHostViewViews::GetRenderWidgetHost() const {
|
| @@ -249,13 +408,11 @@ void RenderWidgetHostViewViews::SetIsLoading(bool is_loading) {
|
| void RenderWidgetHostViewViews::ImeUpdateTextInputState(
|
| WebKit::WebTextInputType type,
|
| const gfx::Rect& caret_rect) {
|
| - // TODO(bryeung): im_context_->UpdateInputMethodState(type, caret_rect);
|
| - NOTIMPLEMENTED();
|
| + ime_context_->ImeUpdateTextInputState(type, caret_rect);
|
| }
|
|
|
| void RenderWidgetHostViewViews::ImeCancelComposition() {
|
| - // TODO(bryeung): im_context_->CancelComposition();
|
| - NOTIMPLEMENTED();
|
| + ime_context_->Reset();
|
| }
|
|
|
| void RenderWidgetHostViewViews::DidUpdateBackingStore(
|
| @@ -509,53 +666,15 @@ bool RenderWidgetHostViewViews::OnMouseWheel(const views::MouseWheelEvent& e) {
|
| return true;
|
| }
|
|
|
| -bool RenderWidgetHostViewViews::OnKeyPressed(const views::KeyEvent &e) {
|
| - // Send key event to input method.
|
| - // TODO host_view->im_context_->ProcessKeyEvent(event);
|
| -
|
| - // This is how it works:
|
| - // (1) If a RawKeyDown event is an accelerator for a reserved command (see
|
| - // Browser::IsReservedCommand), then the command is executed. Otherwise,
|
| - // the event is first sent off to the renderer. The renderer is also
|
| - // notified whether the event would trigger an accelerator in the browser.
|
| - // (2) A Char event is then sent to the renderer.
|
| - // (3) If the renderer does not process the event in step (1), and the event
|
| - // triggers an accelerator, then it will ignore the event in step (2). The
|
| - // renderer also sends back notification to the browser for both steps (1)
|
| - // and (2) about whether the events were processed or not. If the event
|
| - // for (1) is not processed by the renderer, then it is processed by the
|
| - // browser, and (2) is ignored.
|
| -
|
| - NativeWebKeyboardEvent wke;
|
| - wke.type = WebKit::WebInputEvent::RawKeyDown;
|
| - wke.windowsKeyCode = e.key_code();
|
| - wke.setKeyIdentifierFromWindowsKeyCode();
|
| -
|
| - wke.text[0] = wke.unmodifiedText[0] =
|
| - static_cast<unsigned short>(gdk_keyval_to_unicode(
|
| - ui::GdkKeyCodeForWindowsKeyCode(e.key_code(),
|
| - e.IsShiftDown() ^ e.IsCapsLockDown())));
|
| -
|
| - wke.modifiers = WebInputEventFlagsFromViewsEvent(e);
|
| - ForwardKeyboardEvent(wke);
|
| -
|
| - // send the keypress event
|
| - wke.type = WebKit::WebInputEvent::Char;
|
| - ForwardKeyboardEvent(wke);
|
| -
|
| +bool RenderWidgetHostViewViews::OnKeyPressed(const views::KeyEvent& e) {
|
| + if (!ime_context_->FilterKeyEvent(e))
|
| + ForwardKeyEvent(e);
|
| return TRUE;
|
| }
|
|
|
| -bool RenderWidgetHostViewViews::OnKeyReleased(const views::KeyEvent &e) {
|
| - // TODO(bryeung): deal with input methods
|
| - NativeWebKeyboardEvent wke;
|
| -
|
| - wke.type = WebKit::WebInputEvent::KeyUp;
|
| - wke.windowsKeyCode = e.key_code();
|
| - wke.setKeyIdentifierFromWindowsKeyCode();
|
| -
|
| - ForwardKeyboardEvent(wke);
|
| -
|
| +bool RenderWidgetHostViewViews::OnKeyReleased(const views::KeyEvent& e) {
|
| + if (!ime_context_->FilterKeyEvent(e))
|
| + ForwardKeyEvent(e);
|
| return TRUE;
|
| }
|
|
|
| @@ -585,7 +704,7 @@ void RenderWidgetHostViewViews::DidGainFocus() {
|
| GetRenderWidgetHost()->ForwardMouseEvent(fake_event);
|
| }
|
| #endif
|
| -
|
| + ime_context_->Focus();
|
| ShowCurrentCursor();
|
| GetRenderWidgetHost()->GotFocus();
|
| }
|
| @@ -595,6 +714,7 @@ void RenderWidgetHostViewViews::WillLoseFocus() {
|
| // focus.
|
| if (!is_showing_context_menu_ && !is_hidden_)
|
| GetRenderWidgetHost()->Blur();
|
| + ime_context_->Blur();
|
| }
|
|
|
|
|
| @@ -660,19 +780,63 @@ WebKit::WebMouseEvent RenderWidgetHostViewViews::WebMouseEventFromViewsEvent(
|
| return wmevent;
|
| }
|
|
|
| -void RenderWidgetHostViewViews::ForwardKeyboardEvent(
|
| +void RenderWidgetHostViewViews::ForwardKeyEvent(
|
| + const views::KeyEvent& event) {
|
| + // This is how it works:
|
| + // (1) If a RawKeyDown event is an accelerator for a reserved command (see
|
| + // Browser::IsReservedCommand), then the command is executed. Otherwise,
|
| + // the event is first sent off to the renderer. The renderer is also
|
| + // notified whether the event would trigger an accelerator in the browser.
|
| + // (2) A Char event is then sent to the renderer.
|
| + // (3) If the renderer does not process the event in step (1), and the event
|
| + // triggers an accelerator, then it will ignore the event in step (2). The
|
| + // renderer also sends back notification to the browser for both steps (1)
|
| + // and (2) about whether the events were processed or not. If the event
|
| + // for (1) is not processed by the renderer, then it is processed by the
|
| + // browser, and (2) is ignored.
|
| + if (event.type() == ui::ET_KEY_PRESSED) {
|
| + NativeWebKeyboardEvent wke;
|
| +
|
| + wke.type = WebKit::WebInputEvent::RawKeyDown;
|
| + wke.windowsKeyCode = event.key_code();
|
| + wke.setKeyIdentifierFromWindowsKeyCode();
|
| +
|
| + int keyval = ui::GdkKeyCodeForWindowsKeyCode(event.key_code(),
|
| + event.IsShiftDown() ^ event.IsCapsLockDown());
|
| +
|
| + wke.text[0] = wke.unmodifiedText[0] =
|
| + static_cast<unsigned short>(gdk_keyval_to_unicode(keyval));
|
| +
|
| + wke.modifiers = WebInputEventFlagsFromViewsEvent(event);
|
| +
|
| + ForwardWebKeyboardEvent(wke);
|
| +
|
| + wke.type = WebKit::WebInputEvent::Char;
|
| + ForwardWebKeyboardEvent(wke);
|
| + } else {
|
| + NativeWebKeyboardEvent wke;
|
| +
|
| + wke.type = WebKit::WebInputEvent::KeyUp;
|
| + wke.windowsKeyCode = event.key_code();
|
| + wke.setKeyIdentifierFromWindowsKeyCode();
|
| + ForwardWebKeyboardEvent(wke);
|
| + }
|
| +}
|
| +
|
| +void RenderWidgetHostViewViews::ForwardWebKeyboardEvent(
|
| const NativeWebKeyboardEvent& event) {
|
| if (!host_)
|
| return;
|
|
|
| EditCommands edit_commands;
|
| #if 0
|
| -TODO(bryeung): key bindings
|
| + // TODO(bryeung): key bindings
|
| if (!event.skip_in_browser &&
|
| key_bindings_handler_->Match(event, &edit_commands)) {
|
| host_->ForwardEditCommandsForNextKeyEvent(edit_commands);
|
| }
|
| #endif
|
| +
|
| host_->ForwardKeyboardEvent(event);
|
| }
|
|
|
|
|