diff options
author | Kristian Monsen <kristianm@google.com> | 2011-05-31 20:30:28 +0100 |
---|---|---|
committer | Kristian Monsen <kristianm@google.com> | 2011-06-14 20:31:41 -0700 |
commit | 72a454cd3513ac24fbdd0e0cb9ad70b86a99b801 (patch) | |
tree | 382278a54ce7a744d62fa510a9a80688cc12434b /chrome/browser/renderer_host/render_widget_host_view_views.cc | |
parent | c4becdd46e31d261b930e4b5a539cbc1d45c23a6 (diff) | |
download | external_chromium-72a454cd3513ac24fbdd0e0cb9ad70b86a99b801.zip external_chromium-72a454cd3513ac24fbdd0e0cb9ad70b86a99b801.tar.gz external_chromium-72a454cd3513ac24fbdd0e0cb9ad70b86a99b801.tar.bz2 |
Merge Chromium.org at r11.0.672.0: Initial merge by git.
Change-Id: I8b4aaf611a2a405fe3fe10e8a94ea7658645c192
Diffstat (limited to 'chrome/browser/renderer_host/render_widget_host_view_views.cc')
-rw-r--r-- | chrome/browser/renderer_host/render_widget_host_view_views.cc | 454 |
1 files changed, 342 insertions, 112 deletions
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 a8049cf..cd38138 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_views.cc +++ b/chrome/browser/renderer_host/render_widget_host_view_views.cc @@ -7,9 +7,6 @@ #include <algorithm> #include <string> -#include "app/keyboard_code_conversion_gtk.h" -#include "app/l10n_util.h" -#include "app/x11_util.h" #include "base/command_line.h" #include "base/logging.h" #include "base/message_loop.h" @@ -17,29 +14,64 @@ #include "base/string_number_conversions.h" #include "base/task.h" #include "base/time.h" +#include "chrome/browser/renderer_host/backing_store_skia.h" #include "chrome/browser/renderer_host/backing_store_x.h" #include "chrome/browser/renderer_host/render_widget_host.h" -#include "chrome/common/chrome_switches.h" #include "chrome/common/native_web_keyboard_event.h" #include "chrome/common/render_messages.h" #include "chrome/common/result_codes.h" -#include "gfx/canvas.h" -#include "third_party/WebKit/WebKit/chromium/public/gtk/WebInputEventFactory.h" -#include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h" -#include "views/event.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/gtk/WebInputEventFactory.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h" +#include "ui/base/keycodes/keyboard_code_conversion_gtk.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/base/x/x11_util.h" +#include "ui/gfx/canvas.h" +#include "ui/gfx/canvas_skia.h" +#include "views/events/event.h" +#include "views/ime/ime_context.h" #include "views/widget/widget.h" #include "views/widget/widget_gtk.h" static const int kMaxWindowWidth = 4000; static const int kMaxWindowHeight = 4000; -static const char* kRenderWidgetHostViewKey = "__RENDER_WIDGET_HOST_VIEW__"; +static const char kRenderWidgetHostViewKey[] = "__RENDER_WIDGET_HOST_VIEW__"; +static const char kBackingStoreSkiaSwitch[] = "use-backing-store-skia"; + +// 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; +const char RenderWidgetHostViewViews::kViewClassName[] = + "browser/renderer_host/RenderWidgetHostViewViews"; + namespace { +bool UsingBackingStoreSkia() { + static bool decided = false; + static bool use_skia = false; + if (!decided) { + CommandLine* cmdline = CommandLine::ForCurrentProcess(); + use_skia = (cmdline && cmdline->HasSwitch(kBackingStoreSkiaSwitch)); + decided = true; + } + + return use_skia; +} + int WebInputEventFlagsFromViewsEvent(const views::Event& event) { int modifiers = 0; @@ -57,14 +89,14 @@ int WebInputEventFlagsFromViewsEvent(const views::Event& event) { WebKit::WebTouchPoint::State TouchPointStateFromEvent( const views::TouchEvent* event) { - switch (event->GetType()) { - case views::Event::ET_TOUCH_PRESSED: + switch (event->type()) { + case ui::ET_TOUCH_PRESSED: return WebKit::WebTouchPoint::StatePressed; - case views::Event::ET_TOUCH_RELEASED: + case ui::ET_TOUCH_RELEASED: return WebKit::WebTouchPoint::StateReleased; - case views::Event::ET_TOUCH_MOVED: + case ui::ET_TOUCH_MOVED: return WebKit::WebTouchPoint::StateMoved; - case views::Event::ET_TOUCH_CANCELLED: + case ui::ET_TOUCH_CANCELLED: return WebKit::WebTouchPoint::StateCancelled; default: return WebKit::WebTouchPoint::StateUndefined; @@ -73,14 +105,14 @@ WebKit::WebTouchPoint::State TouchPointStateFromEvent( WebKit::WebInputEvent::Type TouchEventTypeFromEvent( const views::TouchEvent* event) { - switch (event->GetType()) { - case views::Event::ET_TOUCH_PRESSED: + switch (event->type()) { + case ui::ET_TOUCH_PRESSED: return WebKit::WebInputEvent::TouchStart; - case views::Event::ET_TOUCH_RELEASED: + case ui::ET_TOUCH_RELEASED: return WebKit::WebInputEvent::TouchEnd; - case views::Event::ET_TOUCH_MOVED: + case ui::ET_TOUCH_MOVED: return WebKit::WebInputEvent::TouchMove; - case views::Event::ET_TOUCH_CANCELLED: + case ui::ET_TOUCH_CANCELLED: return WebKit::WebInputEvent::TouchCancel; default: return WebKit::WebInputEvent::Undefined; @@ -111,6 +143,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) { @@ -125,19 +300,17 @@ RenderWidgetHostViewViews::RenderWidgetHostViewViews(RenderWidgetHost* host) native_cursor_(NULL), is_showing_context_menu_(false), visually_deemphasized_(false), - touch_event_() - { + touch_event_() { SetFocusable(true); host_->set_view(this); } RenderWidgetHostViewViews::~RenderWidgetHostViewViews() { - RenderViewGone(base::TERMINATION_STATUS_NORMAL_TERMINATION, - ResultCodes::NORMAL_EXIT); } void RenderWidgetHostViewViews::InitAsChild() { Show(); + ime_context_.reset(new IMEContextHandler(this)); } RenderWidgetHost* RenderWidgetHostViewViews::GetRenderWidgetHost() const { @@ -151,8 +324,7 @@ void RenderWidgetHostViewViews::InitAsPopup( NOTIMPLEMENTED(); } -void RenderWidgetHostViewViews::InitAsFullscreen( - RenderWidgetHostView* parent_host_view) { +void RenderWidgetHostViewViews::InitAsFullscreen() { NOTIMPLEMENTED(); } @@ -187,7 +359,7 @@ void RenderWidgetHostViewViews::SetSize(const gfx::Size& size) { if (requested_size_.width() != width || requested_size_.height() != height) { requested_size_ = gfx::Size(width, height); - SetBounds(gfx::Rect(x(), y(), width, height)); + SetBounds(x(), y(), width, height); host_->WasResized(); } } @@ -251,13 +423,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( @@ -286,6 +456,7 @@ void RenderWidgetHostViewViews::DidUpdateBackingStore( else SchedulePaint(rect, false); } + invalid_rect_ = invalid_rect_.Intersect(bounds()); } void RenderWidgetHostViewViews::RenderViewGone(base::TerminationStatus status, @@ -295,8 +466,12 @@ void RenderWidgetHostViewViews::RenderViewGone(base::TerminationStatus status, } void RenderWidgetHostViewViews::Destroy() { - // TODO(anicolao): deal with any special popup cleanup - NOTIMPLEMENTED(); + // host_'s destruction brought us here, null it out so we don't use it + host_ = NULL; + + if (parent()) + parent()->RemoveChildView(this); + MessageLoop::current()->DeleteSoon(FROM_HERE, this); } void RenderWidgetHostViewViews::SetTooltipText(const std::wstring& tip) { @@ -324,15 +499,24 @@ bool RenderWidgetHostViewViews::IsPopup() { BackingStore* RenderWidgetHostViewViews::AllocBackingStore( const gfx::Size& size) { - return new BackingStoreX(host_, size, - x11_util::GetVisualFromGtkWidget(native_view()), - gtk_widget_get_visual(native_view())->depth); + gfx::NativeView nview = GetInnerNativeView(); + if (!nview) + return NULL; + + if (UsingBackingStoreSkia()) { + return new BackingStoreSkia(host_, size); + } else { + return new BackingStoreX(host_, size, + ui::GetVisualFromGtkWidget(nview), + gtk_widget_get_visual(nview)->depth); + } } -gfx::NativeView RenderWidgetHostViewViews::native_view() const { +gfx::NativeView RenderWidgetHostViewViews::GetInnerNativeView() const { // TODO(sad): Ideally this function should be equivalent to GetNativeView, and // WidgetGtk-specific function call should not be necessary. - views::WidgetGtk* widget = static_cast<views::WidgetGtk*>(GetWidget()); + const views::WidgetGtk* widget = + static_cast<const views::WidgetGtk*>(GetWidget()); return widget ? widget->window_contents() : NULL; } @@ -355,7 +539,8 @@ void RenderWidgetHostViewViews::Paint(gfx::Canvas* canvas) { // Paint a "hole" in the canvas so that the render of the web page is on // top of whatever else has already been painted in the views hierarchy. // Later views might still get to paint on top. - canvas->FillRectInt(SK_ColorBLACK, 0, 0, kMaxWindowWidth, kMaxWindowHeight, + canvas->FillRectInt(SK_ColorBLACK, 0, 0, + bounds().width(), bounds().height(), SkXfermode::kClear_Mode); // Don't do any painting if the GPU process is rendering directly @@ -365,7 +550,7 @@ void RenderWidgetHostViewViews::Paint(gfx::Canvas* canvas) { return; } - GdkWindow* window = native_view()->window; + GdkWindow* window = GetInnerNativeView()->window; DCHECK(!about_to_validate_and_paint_); // TODO(anicolao): get the damage somehow @@ -375,8 +560,7 @@ void RenderWidgetHostViewViews::Paint(gfx::Canvas* canvas) { ConvertPointToWidget(this, &origin); about_to_validate_and_paint_ = true; - BackingStoreX* backing_store = static_cast<BackingStoreX*>( - host_->GetBackingStore(true)); + BackingStore* backing_store = host_->GetBackingStore(true); // Calling GetBackingStore maybe have changed |invalid_rect_|... about_to_validate_and_paint_ = false; @@ -391,9 +575,15 @@ void RenderWidgetHostViewViews::Paint(gfx::Canvas* canvas) { if (!visually_deemphasized_) { // In the common case, use XCopyArea. We don't draw more than once, so // we don't need to double buffer. - backing_store->XShowRect(origin, - paint_rect, x11_util::GetX11WindowFromGdkWindow(window)); - } else { + + if (UsingBackingStoreSkia()) { + static_cast<BackingStoreSkia*>(backing_store)->SkiaShowRect( + gfx::Point(paint_rect.x(), paint_rect.y()), canvas); + } else { + static_cast<BackingStoreX*>(backing_store)->XShowRect(origin, + paint_rect, ui::GetX11WindowFromGdkWindow(window)); + } + } else if (!UsingBackingStoreSkia()) { // If the grey blend is showing, we make two drawing calls. Use double // buffering to prevent flicker. Use CairoShowRect because XShowRect // shortcuts GDK's double buffering. @@ -401,7 +591,8 @@ void RenderWidgetHostViewViews::Paint(gfx::Canvas* canvas) { paint_rect.width(), paint_rect.height() }; gdk_window_begin_paint_rect(window, &rect); - backing_store->CairoShowRect(paint_rect, GDK_DRAWABLE(window)); + static_cast<BackingStoreX*>(backing_store)->CairoShowRect( + paint_rect, GDK_DRAWABLE(window)); cairo_t* cr = gdk_cairo_create(window); gdk_cairo_rectangle(cr, &rect); @@ -410,6 +601,9 @@ void RenderWidgetHostViewViews::Paint(gfx::Canvas* canvas) { cairo_destroy(cr); gdk_window_end_paint(window); + } else { + // TODO(sad) + NOTIMPLEMENTED(); } } if (!whiteout_start_time_.is_null()) { @@ -437,7 +631,7 @@ void RenderWidgetHostViewViews::Paint(gfx::Canvas* canvas) { } gfx::NativeCursor RenderWidgetHostViewViews::GetCursorForPoint( - views::Event::EventType type, const gfx::Point& point) { + ui::EventType type, const gfx::Point& point) { return native_cursor_; } @@ -488,66 +682,28 @@ void RenderWidgetHostViewViews::OnMouseExited(const views::MouseEvent& event) { bool RenderWidgetHostViewViews::OnMouseWheel(const views::MouseWheelEvent& e) { WebMouseWheelEvent wmwe; - InitializeWebMouseEventFromViewsEvent(e, GetPosition(), &wmwe); + InitializeWebMouseEventFromViewsEvent(e, GetMirroredPosition(), &wmwe); wmwe.type = WebKit::WebInputEvent::MouseWheel; wmwe.button = WebKit::WebMouseEvent::ButtonNone; // TODO(sadrul): How do we determine if it's a horizontal scroll? - wmwe.deltaY = e.GetOffset(); + wmwe.deltaY = e.offset(); wmwe.wheelTicksY = wmwe.deltaY > 0 ? 1 : -1; GetRenderWidgetHost()->ForwardWheelEvent(wmwe); 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.GetKeyCode(); - wke.setKeyIdentifierFromWindowsKeyCode(); - - wke.text[0] = wke.unmodifiedText[0] = - static_cast<unsigned short>(gdk_keyval_to_unicode( - app::GdkKeyCodeForWindowsKeyCode(e.GetKeyCode(), - 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.GetKeyCode(); - wke.setKeyIdentifierFromWindowsKeyCode(); - - ForwardKeyboardEvent(wke); - +bool RenderWidgetHostViewViews::OnKeyReleased(const views::KeyEvent& e) { + if (!ime_context_->FilterKeyEvent(e)) + ForwardKeyEvent(e); return TRUE; } @@ -577,7 +733,7 @@ void RenderWidgetHostViewViews::DidGainFocus() { GetRenderWidgetHost()->ForwardMouseEvent(fake_event); } #endif - + ime_context_->Focus(); ShowCurrentCursor(); GetRenderWidgetHost()->GotFocus(); } @@ -585,15 +741,16 @@ void RenderWidgetHostViewViews::DidGainFocus() { void RenderWidgetHostViewViews::WillLoseFocus() { // If we are showing a context menu, maintain the illusion that webkit has // focus. - if (!is_showing_context_menu_ && !is_hidden_) - GetRenderWidgetHost()->Blur(); + if (!is_showing_context_menu_ && !is_hidden_ && host_) + host_->Blur(); + ime_context_->Blur(); } void RenderWidgetHostViewViews::ShowCurrentCursor() { // The widget may not have a window. If that's the case, abort mission. This // is the same issue as that explained above in Paint(). - if (!native_view() || !native_view()->window) + if (!GetInnerNativeView() || !GetInnerNativeView()->window) return; native_cursor_ = current_cursor_.GetNativeCursor(); @@ -632,7 +789,7 @@ void RenderWidgetHostViewViews::AcceleratedCompositingActivated( WebKit::WebMouseEvent RenderWidgetHostViewViews::WebMouseEventFromViewsEvent( const views::MouseEvent& event) { WebKit::WebMouseEvent wmevent; - InitializeWebMouseEventFromViewsEvent(event, GetPosition(), &wmevent); + InitializeWebMouseEventFromViewsEvent(event, GetMirroredPosition(), &wmevent); // Setting |wmevent.button| is not necessary for -move events, but it is // necessary for -clicks and -drags. @@ -652,63 +809,127 @@ 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); } -bool RenderWidgetHostViewViews::OnTouchEvent(const views::TouchEvent& e) { +views::View::TouchStatus RenderWidgetHostViewViews::OnTouchEvent( + const views::TouchEvent& e) { // Update the list of touch points first. WebKit::WebTouchPoint* point = NULL; + TouchStatus status = TOUCH_STATUS_UNKNOWN; - switch (e.GetType()) { - case views::Event::ET_TOUCH_PRESSED: + switch (e.type()) { + case ui::ET_TOUCH_PRESSED: // Add a new touch point. if (touch_event_.touchPointsLength < WebTouchEvent::touchPointsLengthCap) { point = &touch_event_.touchPoints[touch_event_.touchPointsLength++]; point->id = e.identity(); + + if (touch_event_.touchPointsLength == 1) { + // A new touch sequence has started. + status = TOUCH_STATUS_START; + + // We also want the focus. + RequestFocus(); + } } break; - case views::Event::ET_TOUCH_RELEASED: - case views::Event::ET_TOUCH_CANCELLED: - case views::Event::ET_TOUCH_MOVED: { + case ui::ET_TOUCH_RELEASED: + case ui::ET_TOUCH_CANCELLED: + case ui::ET_TOUCH_MOVED: { // The touch point should have been added to the event from an earlier // _PRESSED event. So find that. // At the moment, only a maximum of 4 touch-points are allowed. So a // simple loop should be sufficient. - for (int i = 0; i < WebTouchEvent::touchPointsLengthCap; ++i) { + for (int i = 0; i < touch_event_.touchPointsLength; ++i) { point = touch_event_.touchPoints + i; if (point->id == e.identity()) { break; } point = NULL; } - DCHECK(point != NULL) << "Touchpoint not found for event " << e.GetType(); break; } default: - DLOG(WARNING) << "Unknown touch event " << e.GetType(); + DLOG(WARNING) << "Unknown touch event " << e.type(); break; } if (!point) - return false; + return TOUCH_STATUS_UNKNOWN; + + if (status != TOUCH_STATUS_START) + status = TOUCH_STATUS_CONTINUE; // Update the location and state of the point. - UpdateTouchPointPosition(&e, GetPosition(), point); point->state = TouchPointStateFromEvent(&e); + if (point->state == WebKit::WebTouchPoint::StateMoved) { + // It is possible for badly written touch drivers to emit Move events even + // when the touch location hasn't changed. In such cases, consume the event + // and pretend nothing happened. + if (point->position.x == e.x() && point->position.y == e.y()) { + return status; + } + } + UpdateTouchPointPosition(&e, GetMirroredPosition(), point); // Mark the rest of the points as stationary. for (int i = 0; i < touch_event_.touchPointsLength; ++i) { @@ -720,21 +941,30 @@ bool RenderWidgetHostViewViews::OnTouchEvent(const views::TouchEvent& e) { // Update the type of the touch event. touch_event_.type = TouchEventTypeFromEvent(&e); + touch_event_.timeStampSeconds = base::Time::Now().ToDoubleT(); // The event and all the touches have been updated. Dispatch. host_->ForwardTouchEvent(touch_event_); // If the touch was released, then remove it from the list of touch points. - if (e.GetType() == views::Event::ET_TOUCH_RELEASED) { + if (e.type() == ui::ET_TOUCH_RELEASED) { --touch_event_.touchPointsLength; for (int i = point - touch_event_.touchPoints; i < touch_event_.touchPointsLength; ++i) { touch_event_.touchPoints[i] = touch_event_.touchPoints[i + 1]; } + if (touch_event_.touchPointsLength == 0) + status = TOUCH_STATUS_END; + } else if (e.type() == ui::ET_TOUCH_CANCELLED) { + status = TOUCH_STATUS_CANCEL; } - return true; + return status; +} + +std::string RenderWidgetHostViewViews::GetClassName() const { + return kViewClassName; } // static |