diff --git a/BUILD.gn b/BUILD.gn index ef107d549..c65474551 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -443,6 +443,8 @@ static_library("libcef_static") { "libcef/browser/origin_whitelist_impl.h", "libcef/browser/osr/browser_platform_delegate_osr.cc", "libcef/browser/osr/browser_platform_delegate_osr.h", + "libcef/browser/osr/motion_event_osr.cc", + "libcef/browser/osr/motion_event_osr.h", "libcef/browser/osr/osr_accessibility_util.cc", "libcef/browser/osr/osr_accessibility_util.h", "libcef/browser/osr/osr_util.cc", @@ -1993,6 +1995,7 @@ if (is_mac) { "gtk+-2.0", "gthread-2.0", "gtk+-unix-print-2.0", + "xi", ] } diff --git a/include/capi/cef_browser_capi.h b/include/capi/cef_browser_capi.h index b6b4863d6..a9b1f142b 100644 --- a/include/capi/cef_browser_capi.h +++ b/include/capi/cef_browser_capi.h @@ -33,7 +33,7 @@ // by hand. See the translator.README.txt file in the tools directory for // more information. // -// $hash=f99ba0878f8b6313adc7a43ad1fa295304fa9bcb$ +// $hash=15f23de47af54fa690b6c5810e3049f97ae2aabd$ // #ifndef CEF_INCLUDE_CAPI_CEF_BROWSER_CAPI_H_ @@ -617,6 +617,12 @@ typedef struct _cef_browser_host_t { int deltaX, int deltaY); + /// + // Send a touch event to the browser for a windowless browser. + /// + void(CEF_CALLBACK* send_touch_event)(struct _cef_browser_host_t* self, + const struct _cef_touch_event_t* event); + /// // Send a focus event to the browser. /// diff --git a/include/cef_browser.h b/include/cef_browser.h index f32ab2409..133a7a6fe 100644 --- a/include/cef_browser.h +++ b/include/cef_browser.h @@ -638,6 +638,12 @@ class CefBrowserHost : public virtual CefBaseRefCounted { int deltaX, int deltaY) = 0; + /// + // Send a touch event to the browser for a windowless browser. + /// + /*--cef()--*/ + virtual void SendTouchEvent(const CefTouchEvent& event) = 0; + /// // Send a focus event to the browser. /// diff --git a/include/internal/cef_types.h b/include/internal/cef_types.h index 09db7a311..9d93ec958 100644 --- a/include/internal/cef_types.h +++ b/include/internal/cef_types.h @@ -1696,6 +1696,74 @@ typedef struct _cef_mouse_event_t { uint32 modifiers; } cef_mouse_event_t; +/// +// Touch points states types. +/// +typedef enum { + CEF_TET_RELEASED = 0, + CEF_TET_PRESSED, + CEF_TET_MOVED, + CEF_TET_CANCELLED +} cef_touch_event_type_t; + +/// +// Structure representing touch event information. +/// +typedef struct _cef_touch_event_t { + /// + // Id of a touch point. Must be unique per touch, can be any number except -1. + // Note that a maximum of 16 concurrent touches will be tracked; touches + // beyond that will be ignored. + /// + int id; + + /// + // X coordinate relative to the left side of the view. + /// + float x; + + /// + // Y coordinate relative to the top side of the view. + /// + float y; + + /// + // X radius in pixels. Set to 0 if not applicable. + /// + float radius_x; + + /// + // Y radius in pixels. Set to 0 if not applicable. + /// + float radius_y; + + /// + // Rotation angle in radians. Set to 0 if not applicable. + /// + float rotation_angle; + + /// + // The normalized pressure of the pointer input in the range of [0,1]. + // Set to 0 if not applicable. + /// + float pressure; + + /// + // The state of the touch point. Touches begin with one CEF_TET_PRESSED event + // followed by zero or more CEF_TET_MOVED events and finally one + // CEF_TET_RELEASED or CEF_TET_CANCELLED event. Events not respecting this + // order will be ignored. + /// + cef_touch_event_type_t type; + + /// + // Bit flags describing any pressed modifier keys. See + // cef_event_flags_t for values. + /// + uint32 modifiers; + +} cef_touch_event_t; + /// // Paint element types. /// diff --git a/include/internal/cef_types_wrappers.h b/include/internal/cef_types_wrappers.h index bb539fe00..8144c4e52 100644 --- a/include/internal/cef_types_wrappers.h +++ b/include/internal/cef_types_wrappers.h @@ -481,6 +481,25 @@ struct CefMouseEventTraits { /// typedef CefStructBase CefMouseEvent; +struct CefTouchEventTraits { + typedef cef_touch_event_t struct_type; + + static inline void init(struct_type* s) {} + + static inline void clear(struct_type* s) {} + + static inline void set(const struct_type* src, + struct_type* target, + bool copy) { + *target = *src; + } +}; + +/// +// Class representing a touch event. +/// +typedef CefStructBase CefTouchEvent; + struct CefPopupFeaturesTraits { typedef cef_popup_features_t struct_type; diff --git a/libcef/browser/browser_host_impl.cc b/libcef/browser/browser_host_impl.cc index 406fb35af..019f26fda 100644 --- a/libcef/browser/browser_host_impl.cc +++ b/libcef/browser/browser_host_impl.cc @@ -3697,3 +3697,21 @@ bool CefBrowserHostImpl::Send(IPC::Message* message) { delete message; return false; } + +void CefBrowserHostImpl::SendTouchEvent(const CefTouchEvent& event) { + if (!IsWindowless()) { + NOTREACHED() << "Window rendering is not disabled"; + return; + } + + if (!CEF_CURRENTLY_ON_UIT()) { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefBrowserHostImpl::SendTouchEvent, this, event)); + return; + } + + if (!web_contents() || !platform_delegate_) + return; + + platform_delegate_->SendTouchEvent(event); +} diff --git a/libcef/browser/browser_host_impl.h b/libcef/browser/browser_host_impl.h index 5c65eea03..8e10b876d 100644 --- a/libcef/browser/browser_host_impl.h +++ b/libcef/browser/browser_host_impl.h @@ -222,6 +222,7 @@ class CefBrowserHostImpl : public CefBrowserHost, void SendMouseWheelEvent(const CefMouseEvent& event, int deltaX, int deltaY) override; + void SendTouchEvent(const CefTouchEvent& event) override; void SendFocusEvent(bool setFocus) override; void SendCaptureLostEvent() override; void NotifyMoveOrResizeStarted() override; diff --git a/libcef/browser/browser_platform_delegate.h b/libcef/browser/browser_platform_delegate.h index 0e8120a27..b6b5d631c 100644 --- a/libcef/browser/browser_platform_delegate.h +++ b/libcef/browser/browser_platform_delegate.h @@ -22,6 +22,7 @@ namespace blink { class WebMouseEvent; class WebMouseWheelEvent; class WebInputEvent; +class WebTouchEvent; } // namespace blink namespace content { @@ -150,6 +151,9 @@ class CefBrowserPlatformDelegate { virtual void SendMouseEvent(const blink::WebMouseEvent& event) = 0; virtual void SendMouseWheelEvent(const blink::WebMouseWheelEvent& event) = 0; + // Send touch events. + virtual void SendTouchEvent(const CefTouchEvent& event) = 0; + // Send focus event. The browser's WebContents may be NULL when this method is // called. virtual void SendFocusEvent(bool setFocus) = 0; diff --git a/libcef/browser/extensions/browser_platform_delegate_background.cc b/libcef/browser/extensions/browser_platform_delegate_background.cc index f6df5b48f..c3e39e31d 100644 --- a/libcef/browser/extensions/browser_platform_delegate_background.cc +++ b/libcef/browser/extensions/browser_platform_delegate_background.cc @@ -66,6 +66,11 @@ void CefBrowserPlatformDelegateBackground::SendMouseWheelEvent( // Nothing to do here. } +void CefBrowserPlatformDelegateBackground::SendTouchEvent( + const CefTouchEvent& event) { + // Nothing to do here. +} + void CefBrowserPlatformDelegateBackground::SendFocusEvent(bool setFocus) { // Nothing to do here. } diff --git a/libcef/browser/extensions/browser_platform_delegate_background.h b/libcef/browser/extensions/browser_platform_delegate_background.h index 07c0b6d35..cade8be6d 100644 --- a/libcef/browser/extensions/browser_platform_delegate_background.h +++ b/libcef/browser/extensions/browser_platform_delegate_background.h @@ -28,6 +28,7 @@ class CefBrowserPlatformDelegateBackground void SendKeyEvent(const content::NativeWebKeyboardEvent& event) override; void SendMouseEvent(const blink::WebMouseEvent& event) override; void SendMouseWheelEvent(const blink::WebMouseWheelEvent& event) override; + void SendTouchEvent(const CefTouchEvent& event) override; void SendFocusEvent(bool setFocus) override; gfx::Point GetScreenPoint(const gfx::Point& view) const override; void ViewText(const std::string& text) override; diff --git a/libcef/browser/native/browser_platform_delegate_native.cc b/libcef/browser/native/browser_platform_delegate_native.cc index 45ec9f74a..d056bb88a 100644 --- a/libcef/browser/native/browser_platform_delegate_native.cc +++ b/libcef/browser/native/browser_platform_delegate_native.cc @@ -59,6 +59,9 @@ void CefBrowserPlatformDelegateNative::SendMouseWheelEvent( host->GetWidget()->ForwardWheelEvent(event); } +void CefBrowserPlatformDelegateNative::SendTouchEvent( + const CefTouchEvent& event) {} + bool CefBrowserPlatformDelegateNative::IsWindowless() const { return false; } diff --git a/libcef/browser/native/browser_platform_delegate_native.h b/libcef/browser/native/browser_platform_delegate_native.h index 6f6befd73..f87132b83 100644 --- a/libcef/browser/native/browser_platform_delegate_native.h +++ b/libcef/browser/native/browser_platform_delegate_native.h @@ -32,6 +32,7 @@ class CefBrowserPlatformDelegateNative : public CefBrowserPlatformDelegate { void SendKeyEvent(const content::NativeWebKeyboardEvent& event) override; void SendMouseEvent(const blink::WebMouseEvent& event) override; void SendMouseWheelEvent(const blink::WebMouseWheelEvent& event) override; + void SendTouchEvent(const CefTouchEvent& event) override; bool IsWindowless() const override; bool IsViewsHosted() const override; diff --git a/libcef/browser/osr/browser_platform_delegate_osr.cc b/libcef/browser/osr/browser_platform_delegate_osr.cc index 9e8a346e4..e79e5a2d0 100644 --- a/libcef/browser/osr/browser_platform_delegate_osr.cc +++ b/libcef/browser/osr/browser_platform_delegate_osr.cc @@ -17,6 +17,7 @@ #include "content/browser/renderer_host/render_widget_host_input_event_router.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/public/browser/render_view_host.h" +#include "ui/events/base_event_utils.h" CefBrowserPlatformDelegateOsr::CefBrowserPlatformDelegateOsr( std::unique_ptr native_delegate) @@ -109,6 +110,12 @@ void CefBrowserPlatformDelegateOsr::SendMouseWheelEvent( view->SendMouseWheelEvent(event); } +void CefBrowserPlatformDelegateOsr::SendTouchEvent(const CefTouchEvent& event) { + CefRenderWidgetHostViewOSR* view = GetOSRHostView(); + if (view) + view->SendTouchEvent(event); +} + void CefBrowserPlatformDelegateOsr::SendFocusEvent(bool setFocus) { CefRenderWidgetHostViewOSR* view = GetOSRHostView(); if (view) diff --git a/libcef/browser/osr/browser_platform_delegate_osr.h b/libcef/browser/osr/browser_platform_delegate_osr.h index 56105d8aa..46b291aa2 100644 --- a/libcef/browser/osr/browser_platform_delegate_osr.h +++ b/libcef/browser/osr/browser_platform_delegate_osr.h @@ -35,6 +35,7 @@ class CefBrowserPlatformDelegateOsr void SendKeyEvent(const content::NativeWebKeyboardEvent& event) override; void SendMouseEvent(const blink::WebMouseEvent& event) override; void SendMouseWheelEvent(const blink::WebMouseWheelEvent& event) override; + void SendTouchEvent(const CefTouchEvent& event) override; void SendFocusEvent(bool setFocus) override; gfx::Point GetScreenPoint(const gfx::Point& view) const override; void ViewText(const std::string& text) override; diff --git a/libcef/browser/osr/motion_event_osr.cc b/libcef/browser/osr/motion_event_osr.cc new file mode 100644 index 000000000..6706f1b75 --- /dev/null +++ b/libcef/browser/osr/motion_event_osr.cc @@ -0,0 +1,218 @@ +// Copyright (c) 2017 The Chromium Embedded Framework Authors. +// Portions 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 "libcef/browser/osr/motion_event_osr.h" + +#include + +#include "ui/events/base_event_utils.h" +#include "ui/events/gesture_detection/gesture_configuration.h" + +CefMotionEventOSR::CefMotionEventOSR() { + std::fill(id_map_, id_map_ + blink::WebTouchEvent::kTouchesLengthCap, -1); +} + +CefMotionEventOSR::~CefMotionEventOSR() {} + +int CefMotionEventOSR::GetSourceDeviceId(size_t pointer_index) const { + if (IsValidIndex(pointer_index)) + return pointer(pointer_index).source_device_id; + else + return -1; +} + +// Returns true if the touch was valid. +bool CefMotionEventOSR::OnTouch(const CefTouchEvent& touch) { + int id = LookupId(touch.id); + bool pointer_id_is_active = id != -1; + + if (touch.type == CEF_TET_PRESSED && pointer_id_is_active) { + // Ignore pressed events for already active touches. + return false; + } else if (touch.type != CEF_TET_PRESSED && !pointer_id_is_active) { + // When a window begins capturing touch events, we could have an active + // touch stream transfered to us, resulting in touch move or touch up + // events without associated touch down events. Ignore them. + return false; + } + + switch (touch.type) { + case CEF_TET_PRESSED: + id = AddId(touch.id); + if (id == -1) + return false; + if (!AddTouch(touch, id)) + return false; + break; + + case CEF_TET_MOVED: { + // Discard if touch is stationary. + int index = FindPointerIndexOfId(id); + if (IsValidIndex(index) && + (touch.x == GetX(index) && touch.y == GetY(index))) { + return false; + } + } + [[fallthrough]]; + // No break. + case CEF_TET_RELEASED: + case CEF_TET_CANCELLED: + // Removing these touch points needs to be postponed until after the + // MotionEvent has been dispatched. This cleanup occurs in + // CleanupRemovedTouchPoints. + UpdateTouch(touch, id); + break; + } + + UpdateCachedAction(touch, id); + set_unique_event_id(ui::GetNextTouchEventId()); + set_flags(touch.modifiers); + set_event_time(base::TimeTicks::Now()); + return true; +} + +// We can't cleanup removed touch points immediately upon receipt of a +// TouchCancel or TouchRelease, as the MotionEvent needs to be able to report +// information about those touch events. Once the MotionEvent has been +// processed, we call CleanupRemovedTouchPoints to do the required +// book-keeping. +void CefMotionEventOSR::CleanupRemovedTouchPoints(const CefTouchEvent& event) { + if (event.type != CEF_TET_RELEASED && event.type != CEF_TET_CANCELLED) { + return; + } + + DCHECK(GetPointerCount()); + + int id = LookupId(event.id); + int index_to_delete = FindPointerIndexOfId(id); + set_action_index(-1); + set_action(ui::MotionEvent::Action::NONE); + if (IsValidIndex(index_to_delete)) { + pointer(index_to_delete) = pointer(GetPointerCount() - 1); + PopPointer(); + RemoveId(event.id); + } +} + +// Reset unchanged touch point to StateStationary for touchmove and touchcancel. +void CefMotionEventOSR::MarkUnchangedTouchPointsAsStationary( + blink::WebTouchEvent* event, + const CefTouchEvent& cef_event) { + int id = LookupId(cef_event.id); + if (event->GetType() == blink::WebInputEvent::kTouchMove || + event->GetType() == blink::WebInputEvent::kTouchCancel) { + for (size_t i = 0; i < event->touches_length; ++i) { + if (event->touches[i].id != id) + event->touches[i].state = blink::WebTouchPoint::kStateStationary; + } + } +} + +int CefMotionEventOSR::LookupId(int id) { + if (id == -1) + return -1; + + for (int i = 0; i < blink::WebTouchEvent::kTouchesLengthCap; i++) { + if (id_map_[i] == id) { + return i; + } + } + return -1; +} + +int CefMotionEventOSR::AddId(int id) { + if (id == -1 || LookupId(id) >= 0) + return -1; + + for (int i = 0; i < blink::WebTouchEvent::kTouchesLengthCap; i++) { + if (id_map_[i] == -1) { + id_map_[i] = id; + return i; + } + } + + return -1; +} + +void CefMotionEventOSR::RemoveId(int id) { + for (int i = 0; i < blink::WebTouchEvent::kTouchesLengthCap; i++) { + if (id_map_[i] == id) { + id_map_[i] = -1; + } + } +} + +bool CefMotionEventOSR::AddTouch(const CefTouchEvent& touch, int id) { + if (GetPointerCount() == MotionEvent::MAX_TOUCH_POINT_COUNT) + return false; + + PushPointer(GetPointerPropertiesFromTouchEvent(touch, id)); + return true; +} + +void CefMotionEventOSR::UpdateTouch(const CefTouchEvent& touch, int id) { + int index_to_update = FindPointerIndexOfId(id); + if (IsValidIndex(index_to_update)) + pointer(index_to_update) = GetPointerPropertiesFromTouchEvent(touch, id); +} + +void CefMotionEventOSR::UpdateCachedAction(const CefTouchEvent& touch, int id) { + DCHECK(GetPointerCount()); + switch (touch.type) { + case CEF_TET_PRESSED: + if (GetPointerCount() == 1) { + set_action(ui::MotionEvent::Action::DOWN); + } else { + set_action(ui::MotionEvent::Action::POINTER_DOWN); + set_action_index(FindPointerIndexOfId(id)); + } + break; + case CEF_TET_RELEASED: + if (GetPointerCount() == 1) { + set_action(ui::MotionEvent::Action::UP); + } else { + set_action(ui::MotionEvent::Action::POINTER_UP); + set_action_index(FindPointerIndexOfId(id)); + } + break; + case CEF_TET_CANCELLED: + set_action(ui::MotionEvent::Action::CANCEL); + break; + case CEF_TET_MOVED: + set_action(ui::MotionEvent::Action::MOVE); + break; + } +} + +bool CefMotionEventOSR::IsValidIndex(int index) const { + return (index >= 0) && (index < static_cast(GetPointerCount())); +} + +ui::PointerProperties CefMotionEventOSR::GetPointerPropertiesFromTouchEvent( + const CefTouchEvent& touch, + int id) { + ui::PointerProperties pointer_properties; + pointer_properties.x = touch.x; + pointer_properties.y = touch.y; + pointer_properties.raw_x = touch.x; + pointer_properties.raw_y = touch.y; + pointer_properties.id = id; + pointer_properties.pressure = touch.pressure; + pointer_properties.source_device_id = 0; + + pointer_properties.SetAxesAndOrientation(touch.radius_x, touch.radius_y, + touch.rotation_angle); + if (!pointer_properties.touch_major) { + pointer_properties.touch_major = + 2.f * ui::GestureConfiguration::GetInstance()->default_radius(); + pointer_properties.touch_minor = + 2.f * ui::GestureConfiguration::GetInstance()->default_radius(); + pointer_properties.orientation = 0; + } + + pointer_properties.tool_type = ui::MotionEvent::ToolType::FINGER; + + return pointer_properties; +} diff --git a/libcef/browser/osr/motion_event_osr.h b/libcef/browser/osr/motion_event_osr.h new file mode 100644 index 000000000..f0db7ea6d --- /dev/null +++ b/libcef/browser/osr/motion_event_osr.h @@ -0,0 +1,59 @@ +// Copyright (c) 2017 The Chromium Embedded Framework Authors. +// Portions 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. + +#ifndef CEF_LIBCEF_BROWSER_OSR_MOTION_EVENT_OSR_H_ +#define CEF_LIBCEF_BROWSER_OSR_MOTION_EVENT_OSR_H_ +#pragma once + +#include "include/cef_base.h" + +#include "third_party/blink/public/platform/web_touch_event.h" +#include "ui/events/gesture_detection/motion_event_generic.h" + +// Implementation of MotionEvent which takes a stream of CefTouchEvents. +// This class is based on ui::MotionEventAura. +class CefMotionEventOSR : public ui::MotionEventGeneric { + public: + CefMotionEventOSR(); + ~CefMotionEventOSR() override; + + int GetSourceDeviceId(size_t pointer_index) const override; + + // Returns true if the touch was valid. + bool OnTouch(const CefTouchEvent& touch); + + // We can't cleanup removed touch points immediately upon receipt of a + // TouchCancel or TouchRelease, as the MotionEvent needs to be able to report + // information about those touch events. Once the MotionEvent has been + // processed, we call CleanupRemovedTouchPoints to do the required + // book-keeping. + void CleanupRemovedTouchPoints(const CefTouchEvent& event); + + // Reset unchanged touch point to StateStationary for touchmove and + // touchcancel to make sure only send one ack per WebTouchEvent. + void MarkUnchangedTouchPointsAsStationary(blink::WebTouchEvent* event, + const CefTouchEvent& cef_event); + + private: + // Chromium can't cope with touch ids >31, so let's map the incoming + // ids to a safe range. + int id_map_[blink::WebTouchEvent::kTouchesLengthCap]; + + int LookupId(int id); + int AddId(int id); + void RemoveId(int id); + + bool AddTouch(const CefTouchEvent& touch, int id); + void UpdateTouch(const CefTouchEvent& touch, int id); + void UpdateCachedAction(const CefTouchEvent& touch, int id); + bool IsValidIndex(int index) const; + ui::PointerProperties GetPointerPropertiesFromTouchEvent( + const CefTouchEvent& touch, + int id); + + DISALLOW_COPY_AND_ASSIGN(CefMotionEventOSR); +}; + +#endif diff --git a/libcef/browser/osr/render_widget_host_view_osr.cc b/libcef/browser/osr/render_widget_host_view_osr.cc index 96818021c..be6a40b88 100644 --- a/libcef/browser/osr/render_widget_host_view_osr.cc +++ b/libcef/browser/osr/render_widget_host_view_osr.cc @@ -31,9 +31,12 @@ #include "content/browser/renderer_host/cursor_manager.h" #include "content/browser/renderer_host/delegated_frame_host.h" #include "content/browser/renderer_host/dip_util.h" +#include "content/browser/renderer_host/input/motion_event_web.h" #include "content/browser/renderer_host/input/synthetic_gesture_target_base.h" #include "content/browser/renderer_host/render_widget_host_delegate.h" #include "content/browser/renderer_host/render_widget_host_impl.h" +#include "content/browser/renderer_host/render_widget_host_input_event_router.h" +#include "content/common/content_switches_internal.h" #include "content/common/input_messages.h" #include "content/common/view_messages.h" #include "content/public/browser/browser_task_traits.h" @@ -44,6 +47,9 @@ #include "content/public/common/content_switches.h" #include "media/base/video_frame.h" #include "ui/compositor/compositor_vsync_manager.h" +#include "ui/events/blink/blink_event_util.h" +#include "ui/events/gesture_detection/gesture_provider_config_helper.h" +#include "ui/events/gesture_detection/motion_event.h" #include "ui/gfx/geometry/dip_util.h" #include "ui/gfx/geometry/size_conversions.h" @@ -165,6 +171,23 @@ class CefDelegatedFrameHostClient : public content::DelegatedFrameHostClient { #endif // !defined(OS_MACOSX) +ui::GestureProvider::Config CreateGestureProviderConfig() { + ui::GestureProvider::Config config = ui::GetGestureProviderConfig( + ui::GestureProviderConfigType::CURRENT_PLATFORM); + return config; +} + +ui::LatencyInfo CreateLatencyInfo(const blink::WebInputEvent& event) { + ui::LatencyInfo latency_info; + // The latency number should only be added if the timestamp is valid. + base::TimeTicks time = event.TimeStamp(); + if (!time.is_null()) { + latency_info.AddLatencyNumberWithTimestamp( + ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, time, 1); + } + return latency_info; +} + } // namespace // Used for managing copy requests when GPU compositing is enabled. Based on @@ -327,8 +350,11 @@ CefRenderWidgetHostViewOSR::CefRenderWidgetHostViewOSR( child_host_view_(NULL), is_showing_(!render_widget_host_->is_hidden()), is_destroyed_(false), + pinch_zoom_enabled_(content::IsPinchToZoomEnabled()), is_scroll_offset_changed_pending_(false), mouse_wheel_phase_handler_(this), + gesture_provider_(CreateGestureProviderConfig(), this), + forward_touch_to_popup_(false), weak_ptr_factory_(this) { DCHECK(render_widget_host_); DCHECK(!render_widget_host_->GetView()); @@ -399,6 +425,12 @@ CefRenderWidgetHostViewOSR::CefRenderWidgetHostViewOSR( if (GetTextInputManager()) GetTextInputManager()->AddObserver(this); + + if (render_widget_host_->delegate() && + render_widget_host_->delegate()->GetInputEventRouter()) { + render_widget_host_->delegate()->GetInputEventRouter()->AddFrameSinkIdOwner( + GetFrameSinkId(), this); + } } CefRenderWidgetHostViewOSR::~CefRenderWidgetHostViewOSR() { @@ -855,7 +887,13 @@ content::CursorManager* CefRenderWidgetHostViewOSR::GetCursorManager() { return cursor_manager_.get(); } -void CefRenderWidgetHostViewOSR::SetIsLoading(bool is_loading) {} +void CefRenderWidgetHostViewOSR::SetIsLoading(bool is_loading) { + if (!is_loading) + return; + // Make sure gesture detection is fresh. + gesture_provider_.ResetDetection(); + forward_touch_to_popup_ = false; +} void CefRenderWidgetHostViewOSR::RenderProcessGone( base::TerminationStatus status, @@ -1085,6 +1123,14 @@ const viz::FrameSinkId& CefRenderWidgetHostViewOSR::GetFrameSinkId() const { return GetDelegatedFrameHost()->frame_sink_id(); } +viz::FrameSinkId CefRenderWidgetHostViewOSR::GetRootFrameSinkId() { +#if defined(OS_MACOSX) + return browser_compositor_->GetRootFrameSinkId(); +#else + return compositor_->frame_sink_id(); +#endif +} + std::unique_ptr CefRenderWidgetHostViewOSR::CreateSyntheticGestureTarget() { // TODO(cef): This is likely incorrect for OOPIF. @@ -1412,6 +1458,78 @@ void CefRenderWidgetHostViewOSR::SendMouseWheelEvent( } } +void CefRenderWidgetHostViewOSR::SendTouchEvent(const CefTouchEvent& event) { + TRACE_EVENT0("cef", "CefRenderWidgetHostViewOSR::SendTouchEvent"); + + if (!IsPopupWidget() && popup_host_view_) { + if (!forward_touch_to_popup_ && event.type == CEF_TET_PRESSED && + pointer_state_.GetPointerCount() == 0) { + forward_touch_to_popup_ = + popup_host_view_->popup_position_.Contains(event.x, event.y); + } + + if (forward_touch_to_popup_) { + CefTouchEvent popup_event(event); + popup_event.x -= popup_host_view_->popup_position_.x(); + popup_event.y -= popup_host_view_->popup_position_.y(); + popup_host_view_->SendTouchEvent(popup_event); + return; + } + } + + // Update the touch event first. + if (!pointer_state_.OnTouch(event)) + return; + + ui::FilteredGestureProvider::TouchHandlingResult result = + gesture_provider_.OnTouchEvent(pointer_state_); + + blink::WebTouchEvent touch_event = ui::CreateWebTouchEventFromMotionEvent( + pointer_state_, result.moved_beyond_slop_region, false); + + pointer_state_.CleanupRemovedTouchPoints(event); + + // Set unchanged touch point to StateStationary for touchmove and + // touchcancel to make sure only send one ack per WebTouchEvent. + if (!result.succeeded) + pointer_state_.MarkUnchangedTouchPointsAsStationary(&touch_event, event); + + if (!render_widget_host_) + return; + + ui::LatencyInfo latency_info = CreateLatencyInfo(touch_event); + if (ShouldRouteEvents()) { + render_widget_host_->delegate()->GetInputEventRouter()->RouteTouchEvent( + this, &touch_event, latency_info); + } else { + render_widget_host_->ForwardTouchEventWithLatencyInfo(touch_event, + latency_info); + } + + bool touch_end = touch_event.GetType() == blink::WebInputEvent::kTouchEnd || + touch_event.GetType() == blink::WebInputEvent::kTouchCancel; + + if (touch_end && IsPopupWidget() && parent_host_view_ && + parent_host_view_->popup_host_view_ == this) { + parent_host_view_->forward_touch_to_popup_ = false; + } +} + +bool CefRenderWidgetHostViewOSR::ShouldRouteEvents() const { + if (!render_widget_host_->delegate()) + return false; + + // Do not route events that are currently targeted to page popups such as + // +
Drag here
+
+