Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2198)

Unified Diff: chrome/browser/renderer_host/render_widget_host_view_views.cc

Issue 6480036: Add input method support for views and integrate ibus input framework (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/renderer_host/render_widget_host_view_views.h ('k') | views/ime/ibus_ime_context.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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);
}
« no previous file with comments | « chrome/browser/renderer_host/render_widget_host_view_views.h ('k') | views/ime/ibus_ime_context.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698