mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-02-22 06:57:42 +01:00
Add multi-touch support for OSR (issue #1059)
This commit is contained in:
parent
4a3a9c8c35
commit
52d535a6dc
3
BUILD.gn
3
BUILD.gn
@ -445,6 +445,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",
|
||||
@ -1997,6 +1999,7 @@ if (is_mac) {
|
||||
"gtk+-2.0",
|
||||
"gthread-2.0",
|
||||
"gtk+-unix-print-2.0",
|
||||
"xi",
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
///
|
||||
|
@ -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.
|
||||
///
|
||||
|
@ -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.
|
||||
///
|
||||
|
@ -481,6 +481,25 @@ struct CefMouseEventTraits {
|
||||
///
|
||||
typedef CefStructBase<CefMouseEventTraits> 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<CefTouchEventTraits> CefTouchEvent;
|
||||
|
||||
struct CefPopupFeaturesTraits {
|
||||
typedef cef_popup_features_t struct_type;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -59,6 +59,9 @@ void CefBrowserPlatformDelegateNative::SendMouseWheelEvent(
|
||||
host->GetWidget()->ForwardWheelEvent(event);
|
||||
}
|
||||
|
||||
void CefBrowserPlatformDelegateNative::SendTouchEvent(
|
||||
const CefTouchEvent& event) {}
|
||||
|
||||
bool CefBrowserPlatformDelegateNative::IsWindowless() const {
|
||||
return false;
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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<CefBrowserPlatformDelegateNative> 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)
|
||||
|
@ -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;
|
||||
|
218
libcef/browser/osr/motion_event_osr.cc
Normal file
218
libcef/browser/osr/motion_event_osr.cc
Normal file
@ -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 <algorithm>
|
||||
|
||||
#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<int>(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;
|
||||
}
|
59
libcef/browser/osr/motion_event_osr.h
Normal file
59
libcef/browser/osr/motion_event_osr.h
Normal file
@ -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
|
@ -31,8 +31,11 @@
|
||||
#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/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"
|
||||
@ -43,6 +46,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"
|
||||
|
||||
@ -164,6 +170,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
|
||||
@ -326,8 +349,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());
|
||||
@ -398,6 +424,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() {
|
||||
@ -854,7 +886,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,
|
||||
@ -1084,6 +1122,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
|
||||
}
|
||||
|
||||
void CefRenderWidgetHostViewOSR::SetNeedsBeginFrames(bool enabled) {
|
||||
SetFrameRate();
|
||||
|
||||
@ -1403,6 +1449,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
|
||||
// <select> element drop-downs, since these cannot contain cross-process
|
||||
// frames.
|
||||
if (!render_widget_host_->delegate()->IsWidgetForMainFrame(
|
||||
render_widget_host_)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !!render_widget_host_->delegate()->GetInputEventRouter();
|
||||
}
|
||||
|
||||
void CefRenderWidgetHostViewOSR::SendFocusEvent(bool focus) {
|
||||
if (!render_widget_host_)
|
||||
return;
|
||||
@ -1446,6 +1564,41 @@ void CefRenderWidgetHostViewOSR::OnUpdateTextInputStateCalled(
|
||||
handler->OnVirtualKeyboardRequested(browser_impl_->GetBrowser(), mode);
|
||||
}
|
||||
|
||||
void CefRenderWidgetHostViewOSR::ProcessAckedTouchEvent(
|
||||
const content::TouchEventWithLatencyInfo& touch,
|
||||
content::InputEventAckState ack_result) {
|
||||
const bool event_consumed =
|
||||
ack_result == content::INPUT_EVENT_ACK_STATE_CONSUMED;
|
||||
gesture_provider_.OnTouchEventAck(touch.event.unique_touch_event_id,
|
||||
event_consumed, false);
|
||||
}
|
||||
|
||||
void CefRenderWidgetHostViewOSR::OnGestureEvent(
|
||||
const ui::GestureEventData& gesture) {
|
||||
if ((gesture.type() == ui::ET_GESTURE_PINCH_BEGIN ||
|
||||
gesture.type() == ui::ET_GESTURE_PINCH_UPDATE ||
|
||||
gesture.type() == ui::ET_GESTURE_PINCH_END) &&
|
||||
!pinch_zoom_enabled_) {
|
||||
return;
|
||||
}
|
||||
|
||||
blink::WebGestureEvent web_event =
|
||||
ui::CreateWebGestureEventFromGestureEventData(gesture);
|
||||
|
||||
// without this check, forwarding gestures does not work!
|
||||
if (web_event.GetType() == blink::WebInputEvent::kUndefined)
|
||||
return;
|
||||
|
||||
ui::LatencyInfo latency_info = CreateLatencyInfo(web_event);
|
||||
if (ShouldRouteEvents()) {
|
||||
render_widget_host_->delegate()->GetInputEventRouter()->RouteGestureEvent(
|
||||
this, &web_event, latency_info);
|
||||
} else {
|
||||
render_widget_host_->ForwardGestureEventWithLatencyInfo(web_event,
|
||||
latency_info);
|
||||
}
|
||||
}
|
||||
|
||||
void CefRenderWidgetHostViewOSR::UpdateFrameRate() {
|
||||
frame_rate_threshold_us_ = 0;
|
||||
SetFrameRate();
|
||||
@ -1675,6 +1828,9 @@ void CefRenderWidgetHostViewOSR::SendBeginFrame(base::TimeTicks frame_time,
|
||||
DCHECK(begin_frame_args.IsValid());
|
||||
begin_frame_number_++;
|
||||
|
||||
if (render_widget_host_)
|
||||
render_widget_host_->ProgressFlingIfNeeded(frame_time);
|
||||
|
||||
if (renderer_compositor_frame_sink_) {
|
||||
renderer_compositor_frame_sink_->OnBeginFrame(begin_frame_args, {});
|
||||
}
|
||||
|
@ -14,6 +14,8 @@
|
||||
#include "include/cef_base.h"
|
||||
#include "include/cef_browser.h"
|
||||
|
||||
#include "libcef/browser/osr/motion_event_osr.h"
|
||||
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "build/build_config.h"
|
||||
#include "components/viz/common/frame_sinks/begin_frame_source.h"
|
||||
@ -24,6 +26,10 @@
|
||||
#include "content/public/common/widget_type.h"
|
||||
#include "ui/compositor/compositor.h"
|
||||
#include "ui/compositor/external_begin_frame_client.h"
|
||||
#include "ui/events/base_event_utils.h"
|
||||
#include "ui/events/gesture_detection/filtered_gesture_provider.h"
|
||||
#include "ui/events/gesture_detection/gesture_configuration.h"
|
||||
#include "ui/events/gesture_detection/motion_event_generic.h"
|
||||
#include "ui/gfx/geometry/rect.h"
|
||||
|
||||
#if defined(OS_LINUX)
|
||||
@ -98,7 +104,8 @@ class MacHelper;
|
||||
class CefRenderWidgetHostViewOSR : public content::RenderWidgetHostViewBase,
|
||||
public ui::ExternalBeginFrameClient,
|
||||
public ui::CompositorDelegate,
|
||||
public content::TextInputManager::Observer {
|
||||
public content::TextInputManager::Observer,
|
||||
public ui::GestureProviderClient {
|
||||
public:
|
||||
CefRenderWidgetHostViewOSR(SkColor background_color,
|
||||
bool use_shared_texture,
|
||||
@ -202,6 +209,7 @@ class CefRenderWidgetHostViewOSR : public content::RenderWidgetHostViewBase,
|
||||
const viz::LocalSurfaceIdAllocation& GetLocalSurfaceIdAllocation()
|
||||
const override;
|
||||
const viz::FrameSinkId& GetFrameSinkId() const override;
|
||||
viz::FrameSinkId GetRootFrameSinkId() override;
|
||||
|
||||
// ui::ExternalBeginFrameClient implementation:
|
||||
void OnDisplayDidFinishFrame(const viz::BeginFrameAck& ack) override;
|
||||
@ -217,6 +225,11 @@ class CefRenderWidgetHostViewOSR : public content::RenderWidgetHostViewBase,
|
||||
RenderWidgetHostViewBase* updated_view,
|
||||
bool did_update_state) override;
|
||||
|
||||
// ui::GestureProviderClient implementation.
|
||||
void ProcessAckedTouchEvent(const content::TouchEventWithLatencyInfo& touch,
|
||||
content::InputEventAckState ack_result) override;
|
||||
void OnGestureEvent(const ui::GestureEventData& gesture) override;
|
||||
|
||||
bool InstallTransparency();
|
||||
|
||||
void SynchronizeVisualProperties();
|
||||
@ -226,6 +239,8 @@ class CefRenderWidgetHostViewOSR : public content::RenderWidgetHostViewBase,
|
||||
void SendKeyEvent(const content::NativeWebKeyboardEvent& event);
|
||||
void SendMouseEvent(const blink::WebMouseEvent& event);
|
||||
void SendMouseWheelEvent(const blink::WebMouseWheelEvent& event);
|
||||
void SendTouchEvent(const CefTouchEvent& event);
|
||||
bool ShouldRouteEvents() const;
|
||||
void SendFocusEvent(bool focus);
|
||||
void UpdateFrameRate();
|
||||
|
||||
@ -257,6 +272,8 @@ class CefRenderWidgetHostViewOSR : public content::RenderWidgetHostViewBase,
|
||||
}
|
||||
|
||||
void set_popup_host_view(CefRenderWidgetHostViewOSR* popup_view) {
|
||||
if (popup_view != popup_host_view_)
|
||||
forward_touch_to_popup_ = false;
|
||||
popup_host_view_ = popup_view;
|
||||
}
|
||||
void set_child_host_view(CefRenderWidgetHostViewOSR* popup_view) {
|
||||
@ -358,8 +375,8 @@ class CefRenderWidgetHostViewOSR : public content::RenderWidgetHostViewBase,
|
||||
std::unique_ptr<content::BrowserCompositorMac> browser_compositor_;
|
||||
MacHelper* mac_helper_;
|
||||
#elif defined(USE_X11)
|
||||
CefWindowX11* window_;
|
||||
std::unique_ptr<ui::XScopedCursor> invisible_cursor_;
|
||||
CefWindowX11* window_;
|
||||
std::unique_ptr<ui::XScopedCursor> invisible_cursor_;
|
||||
#endif
|
||||
|
||||
std::unique_ptr<content::CursorManager> cursor_manager_;
|
||||
@ -405,6 +422,10 @@ class CefRenderWidgetHostViewOSR : public content::RenderWidgetHostViewBase,
|
||||
base::Lock damage_rect_lock_;
|
||||
std::map<uint32_t, gfx::Rect> damage_rects_;
|
||||
|
||||
// Whether pinch-to-zoom should be enabled and pinch events forwarded to the
|
||||
// renderer.
|
||||
bool pinch_zoom_enabled_;
|
||||
|
||||
// The last scroll offset of the view.
|
||||
gfx::Vector2dF last_scroll_offset_;
|
||||
bool is_scroll_offset_changed_pending_;
|
||||
@ -419,6 +440,12 @@ class CefRenderWidgetHostViewOSR : public content::RenderWidgetHostViewBase,
|
||||
// EnsureSurfaceSynchronizedForLayoutTest().
|
||||
uint32_t latest_capture_sequence_number_ = 0u;
|
||||
|
||||
// ui::GestureProviderClient implementation.
|
||||
ui::FilteredGestureProvider gesture_provider_;
|
||||
|
||||
CefMotionEventOSR pointer_state_;
|
||||
bool forward_touch_to_popup_;
|
||||
|
||||
base::WeakPtrFactory<CefRenderWidgetHostViewOSR> weak_ptr_factory_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CefRenderWidgetHostViewOSR);
|
||||
|
@ -204,6 +204,9 @@ void CefBrowserPlatformDelegateViews::SendMouseWheelEvent(
|
||||
host->GetWidget()->ForwardWheelEvent(event);
|
||||
}
|
||||
|
||||
void CefBrowserPlatformDelegateViews::SendTouchEvent(
|
||||
const CefTouchEvent& event) {}
|
||||
|
||||
void CefBrowserPlatformDelegateViews::SendFocusEvent(bool setFocus) {
|
||||
// Will result in a call to WebContents::Focus().
|
||||
if (setFocus && browser_view_->root_view())
|
||||
|
@ -48,6 +48,7 @@ class CefBrowserPlatformDelegateViews
|
||||
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;
|
||||
|
@ -9,7 +9,7 @@
|
||||
// implementations. See the translator.README.txt file in the tools directory
|
||||
// for more information.
|
||||
//
|
||||
// $hash=9f02385389794ebb639bdd4ac1d4fca435b411ad$
|
||||
// $hash=41e334182e76a4bfc65eca7cbf10e402a115ef64$
|
||||
//
|
||||
|
||||
#include "libcef_dll/cpptoc/browser_host_cpptoc.h"
|
||||
@ -724,6 +724,28 @@ browser_host_send_mouse_wheel_event(struct _cef_browser_host_t* self,
|
||||
deltaY);
|
||||
}
|
||||
|
||||
void CEF_CALLBACK
|
||||
browser_host_send_touch_event(struct _cef_browser_host_t* self,
|
||||
const struct _cef_touch_event_t* event) {
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
DCHECK(self);
|
||||
if (!self)
|
||||
return;
|
||||
// Verify param: event; type: struct_byref_const
|
||||
DCHECK(event);
|
||||
if (!event)
|
||||
return;
|
||||
|
||||
// Translate param: event; type: struct_byref_const
|
||||
CefTouchEvent eventObj;
|
||||
if (event)
|
||||
eventObj.Set(*event, false);
|
||||
|
||||
// Execute
|
||||
CefBrowserHostCppToC::Get(self)->SendTouchEvent(eventObj);
|
||||
}
|
||||
|
||||
void CEF_CALLBACK
|
||||
browser_host_send_focus_event(struct _cef_browser_host_t* self, int setFocus) {
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
@ -1155,6 +1177,7 @@ CefBrowserHostCppToC::CefBrowserHostCppToC() {
|
||||
GetStruct()->send_mouse_click_event = browser_host_send_mouse_click_event;
|
||||
GetStruct()->send_mouse_move_event = browser_host_send_mouse_move_event;
|
||||
GetStruct()->send_mouse_wheel_event = browser_host_send_mouse_wheel_event;
|
||||
GetStruct()->send_touch_event = browser_host_send_touch_event;
|
||||
GetStruct()->send_focus_event = browser_host_send_focus_event;
|
||||
GetStruct()->send_capture_lost_event = browser_host_send_capture_lost_event;
|
||||
GetStruct()->notify_move_or_resize_started =
|
||||
|
@ -9,7 +9,7 @@
|
||||
// implementations. See the translator.README.txt file in the tools directory
|
||||
// for more information.
|
||||
//
|
||||
// $hash=f57448cbd63f9fdff85b1dbf22a09db3f6ecdea1$
|
||||
// $hash=5b3acb2cb74ef6b6b42bade4e0515d39e4609319$
|
||||
//
|
||||
|
||||
#include "libcef_dll/ctocpp/browser_host_ctocpp.h"
|
||||
@ -622,6 +622,18 @@ void CefBrowserHostCToCpp::SendMouseWheelEvent(const CefMouseEvent& event,
|
||||
_struct->send_mouse_wheel_event(_struct, &event, deltaX, deltaY);
|
||||
}
|
||||
|
||||
NO_SANITIZE("cfi-icall")
|
||||
void CefBrowserHostCToCpp::SendTouchEvent(const CefTouchEvent& event) {
|
||||
cef_browser_host_t* _struct = GetStruct();
|
||||
if (CEF_MEMBER_MISSING(_struct, send_touch_event))
|
||||
return;
|
||||
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
// Execute
|
||||
_struct->send_touch_event(_struct, &event);
|
||||
}
|
||||
|
||||
NO_SANITIZE("cfi-icall")
|
||||
void CefBrowserHostCToCpp::SendFocusEvent(bool setFocus) {
|
||||
cef_browser_host_t* _struct = GetStruct();
|
||||
|
@ -9,7 +9,7 @@
|
||||
// implementations. See the translator.README.txt file in the tools directory
|
||||
// for more information.
|
||||
//
|
||||
// $hash=65e39ded61217f1263d5fd3a955843078b9799d2$
|
||||
// $hash=a7acce93e2b4109ddf76e4a82e0ff6d85be1451a$
|
||||
//
|
||||
|
||||
#ifndef CEF_LIBCEF_DLL_CTOCPP_BROWSER_HOST_CTOCPP_H_
|
||||
@ -96,6 +96,7 @@ class CefBrowserHostCToCpp : public CefCToCppRefCounted<CefBrowserHostCToCpp,
|
||||
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;
|
||||
|
@ -39,7 +39,11 @@ patches = [
|
||||
{
|
||||
# Support component builds (GN is_component_build=true).
|
||||
# https://bitbucket.org/chromiumembedded/cef/issues/1617
|
||||
'name': 'component_build_1617',
|
||||
#
|
||||
# Export GetUnicodeCharacterFromXKeySym and XKeySymToDomKey
|
||||
# to fix component builds.
|
||||
# https://bitbucket.org/chromiumembedded/cef/issues/2587
|
||||
'name': 'component_build',
|
||||
},
|
||||
{
|
||||
# Revert change on Windows that removes MessageLoop::os_modal_loop().
|
||||
|
147
patch/patches/component_build.patch
Normal file
147
patch/patches/component_build.patch
Normal file
@ -0,0 +1,147 @@
|
||||
diff --git content/app/content_service_manager_main_delegate.h content/app/content_service_manager_main_delegate.h
|
||||
index 864f2a5a315a..78b71d523e86 100644
|
||||
--- content/app/content_service_manager_main_delegate.h
|
||||
+++ content/app/content_service_manager_main_delegate.h
|
||||
@@ -18,7 +18,8 @@ namespace content {
|
||||
|
||||
class ContentMainRunnerImpl;
|
||||
|
||||
-class ContentServiceManagerMainDelegate : public service_manager::MainDelegate {
|
||||
+class CONTENT_EXPORT ContentServiceManagerMainDelegate :
|
||||
+ public service_manager::MainDelegate {
|
||||
public:
|
||||
explicit ContentServiceManagerMainDelegate(const ContentMainParams& params);
|
||||
~ContentServiceManagerMainDelegate() override;
|
||||
diff --git content/browser/renderer_host/input/mouse_wheel_phase_handler.h content/browser/renderer_host/input/mouse_wheel_phase_handler.h
|
||||
index fc252b6ceffd..b0dfd847ec03 100644
|
||||
--- content/browser/renderer_host/input/mouse_wheel_phase_handler.h
|
||||
+++ content/browser/renderer_host/input/mouse_wheel_phase_handler.h
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include "base/timer/timer.h"
|
||||
#include "content/browser/renderer_host/render_widget_host_delegate.h"
|
||||
+#include "content/common/content_export.h"
|
||||
#include "content/public/common/input_event_ack_state.h"
|
||||
#include "third_party/blink/public/platform/web_mouse_wheel_event.h"
|
||||
|
||||
@@ -55,7 +56,7 @@ enum class FirstScrollUpdateAckState {
|
||||
// The MouseWheelPhaseHandler is responsible for adding the proper phase to
|
||||
// wheel events. Phase information is necessary for wheel scrolling since it
|
||||
// shows the start and end of a scrolling sequence.
|
||||
-class MouseWheelPhaseHandler {
|
||||
+class CONTENT_EXPORT MouseWheelPhaseHandler {
|
||||
public:
|
||||
MouseWheelPhaseHandler(RenderWidgetHostViewBase* const host_view);
|
||||
~MouseWheelPhaseHandler() {}
|
||||
diff --git content/browser/renderer_host/input/synthetic_gesture_target_base.h content/browser/renderer_host/input/synthetic_gesture_target_base.h
|
||||
index 53476354343e..fd1a7a24455b 100644
|
||||
--- content/browser/renderer_host/input/synthetic_gesture_target_base.h
|
||||
+++ content/browser/renderer_host/input/synthetic_gesture_target_base.h
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "base/macros.h"
|
||||
#include "base/time/time.h"
|
||||
#include "content/browser/renderer_host/input/synthetic_gesture_target.h"
|
||||
+#include "content/common/content_export.h"
|
||||
|
||||
namespace ui {
|
||||
class LatencyInfo;
|
||||
@@ -24,7 +25,8 @@ namespace content {
|
||||
|
||||
class RenderWidgetHostImpl;
|
||||
|
||||
-class SyntheticGestureTargetBase : public SyntheticGestureTarget {
|
||||
+class CONTENT_EXPORT SyntheticGestureTargetBase :
|
||||
+ public SyntheticGestureTarget {
|
||||
public:
|
||||
explicit SyntheticGestureTargetBase(RenderWidgetHostImpl* host);
|
||||
~SyntheticGestureTargetBase() override;
|
||||
diff --git content/common/content_switches_internal.h content/common/content_switches_internal.h
|
||||
index 5e67fbce7c9e..5bb9ee518dce 100644
|
||||
--- content/common/content_switches_internal.h
|
||||
+++ content/common/content_switches_internal.h
|
||||
@@ -15,7 +15,7 @@ class CommandLine;
|
||||
|
||||
namespace content {
|
||||
|
||||
-bool IsPinchToZoomEnabled();
|
||||
+CONTENT_EXPORT bool IsPinchToZoomEnabled();
|
||||
|
||||
V8CacheOptions GetV8CacheOptions();
|
||||
|
||||
diff --git third_party/blink/renderer/controller/BUILD.gn third_party/blink/renderer/controller/BUILD.gn
|
||||
index 7668f3725200..665e8e579c54 100644
|
||||
--- third_party/blink/renderer/controller/BUILD.gn
|
||||
+++ third_party/blink/renderer/controller/BUILD.gn
|
||||
@@ -25,6 +25,7 @@ component("controller") {
|
||||
|
||||
configs += [
|
||||
"//build/config/compiler:wexit_time_destructors",
|
||||
+ "//cef/libcef/features:config",
|
||||
"//third_party/blink/renderer:config",
|
||||
"//third_party/blink/renderer:inside_blink",
|
||||
"//third_party/blink/renderer:non_test_config",
|
||||
@@ -47,6 +48,8 @@ component("controller") {
|
||||
"memory_usage_monitor.h",
|
||||
"memory_usage_monitor_android.cc",
|
||||
"memory_usage_monitor_android.h",
|
||||
+ "//cef/libcef/renderer/blink_glue.cc",
|
||||
+ "//cef/libcef/renderer/blink_glue.h",
|
||||
]
|
||||
|
||||
if (is_android) {
|
||||
diff --git ui/events/keycodes/BUILD.gn ui/events/keycodes/BUILD.gn
|
||||
index 1e6d31cc0c92..36f3283291d9 100644
|
||||
--- ui/events/keycodes/BUILD.gn
|
||||
+++ ui/events/keycodes/BUILD.gn
|
||||
@@ -14,6 +14,8 @@ jumbo_source_set("xkb") {
|
||||
"xkb_keysym.h",
|
||||
]
|
||||
|
||||
+ defines = [ "KEYCODES_X_IMPLEMENTATION" ]
|
||||
+
|
||||
deps = [
|
||||
"//base",
|
||||
"//ui/base:buildflags",
|
||||
diff --git ui/events/keycodes/keyboard_code_conversion_xkb.h ui/events/keycodes/keyboard_code_conversion_xkb.h
|
||||
index a1f9b78704fb..c7d3558251d9 100644
|
||||
--- ui/events/keycodes/keyboard_code_conversion_xkb.h
|
||||
+++ ui/events/keycodes/keyboard_code_conversion_xkb.h
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include "base/strings/string16.h"
|
||||
#include "ui/events/keycodes/dom/dom_key.h"
|
||||
+#include "ui/events/keycodes/keycodes_x_export.h"
|
||||
#include "ui/events/keycodes/xkb_keysym.h"
|
||||
|
||||
namespace ui {
|
||||
@@ -24,7 +25,7 @@ DomKey NonPrintableXKeySymToDomKey(xkb_keysym_t keysym);
|
||||
// base::char16 DeadXKeySymToCombiningCharacter(xkb_keysym_t keysym);
|
||||
|
||||
// Return the DomKey determined by the XKB layout result (keysym, character).
|
||||
-DomKey XKeySymToDomKey(xkb_keysym_t keysym, base::char16 character);
|
||||
+KEYCODES_X_EXPORT DomKey XKeySymToDomKey(xkb_keysym_t keysym, base::char16 character);
|
||||
|
||||
} // namespace ui
|
||||
|
||||
diff --git ui/events/keycodes/keysym_to_unicode.h ui/events/keycodes/keysym_to_unicode.h
|
||||
index a7983d179832..2bbee48e57ac 100644
|
||||
--- ui/events/keycodes/keysym_to_unicode.h
|
||||
+++ ui/events/keycodes/keysym_to_unicode.h
|
||||
@@ -5,6 +5,8 @@
|
||||
#ifndef UI_EVENTS_KEYCODES_KEYSYM_TO_UNICODE_H_
|
||||
#define UI_EVENTS_KEYCODES_KEYSYM_TO_UNICODE_H_
|
||||
|
||||
+#include "ui/events/keycodes/keycodes_x_export.h"
|
||||
+
|
||||
#include <stdint.h>
|
||||
|
||||
namespace ui {
|
||||
@@ -13,7 +15,7 @@ namespace ui {
|
||||
// |keysym| doesn't represent a printable character, returns zero. We don't
|
||||
// support characters outside the Basic Plane, and this function returns zero
|
||||
// in that case.
|
||||
-uint16_t GetUnicodeCharacterFromXKeySym(unsigned long keysym);
|
||||
+KEYCODES_X_EXPORT uint16_t GetUnicodeCharacterFromXKeySym(unsigned long keysym);
|
||||
|
||||
} // namespace ui
|
||||
|
@ -1,56 +0,0 @@
|
||||
diff --git content/app/content_service_manager_main_delegate.h content/app/content_service_manager_main_delegate.h
|
||||
index 864f2a5a315a..78b71d523e86 100644
|
||||
--- content/app/content_service_manager_main_delegate.h
|
||||
+++ content/app/content_service_manager_main_delegate.h
|
||||
@@ -18,7 +18,8 @@ namespace content {
|
||||
|
||||
class ContentMainRunnerImpl;
|
||||
|
||||
-class ContentServiceManagerMainDelegate : public service_manager::MainDelegate {
|
||||
+class CONTENT_EXPORT ContentServiceManagerMainDelegate :
|
||||
+ public service_manager::MainDelegate {
|
||||
public:
|
||||
explicit ContentServiceManagerMainDelegate(const ContentMainParams& params);
|
||||
~ContentServiceManagerMainDelegate() override;
|
||||
diff --git content/browser/renderer_host/input/mouse_wheel_phase_handler.h content/browser/renderer_host/input/mouse_wheel_phase_handler.h
|
||||
index fc252b6ceffd..b0dfd847ec03 100644
|
||||
--- content/browser/renderer_host/input/mouse_wheel_phase_handler.h
|
||||
+++ content/browser/renderer_host/input/mouse_wheel_phase_handler.h
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include "base/timer/timer.h"
|
||||
#include "content/browser/renderer_host/render_widget_host_delegate.h"
|
||||
+#include "content/common/content_export.h"
|
||||
#include "content/public/common/input_event_ack_state.h"
|
||||
#include "third_party/blink/public/platform/web_mouse_wheel_event.h"
|
||||
|
||||
@@ -55,7 +56,7 @@ enum class FirstScrollUpdateAckState {
|
||||
// The MouseWheelPhaseHandler is responsible for adding the proper phase to
|
||||
// wheel events. Phase information is necessary for wheel scrolling since it
|
||||
// shows the start and end of a scrolling sequence.
|
||||
-class MouseWheelPhaseHandler {
|
||||
+class CONTENT_EXPORT MouseWheelPhaseHandler {
|
||||
public:
|
||||
MouseWheelPhaseHandler(RenderWidgetHostViewBase* const host_view);
|
||||
~MouseWheelPhaseHandler() {}
|
||||
diff --git third_party/blink/renderer/controller/BUILD.gn third_party/blink/renderer/controller/BUILD.gn
|
||||
index 7668f3725200..665e8e579c54 100644
|
||||
--- third_party/blink/renderer/controller/BUILD.gn
|
||||
+++ third_party/blink/renderer/controller/BUILD.gn
|
||||
@@ -25,6 +25,7 @@ component("controller") {
|
||||
|
||||
configs += [
|
||||
"//build/config/compiler:wexit_time_destructors",
|
||||
+ "//cef/libcef/features:config",
|
||||
"//third_party/blink/renderer:config",
|
||||
"//third_party/blink/renderer:inside_blink",
|
||||
"//third_party/blink/renderer:non_test_config",
|
||||
@@ -47,6 +48,8 @@ component("controller") {
|
||||
"memory_usage_monitor.h",
|
||||
"memory_usage_monitor_android.cc",
|
||||
"memory_usage_monitor_android.h",
|
||||
+ "//cef/libcef/renderer/blink_glue.cc",
|
||||
+ "//cef/libcef/renderer/blink_glue.h",
|
||||
]
|
||||
|
||||
if (is_android) {
|
@ -15,6 +15,7 @@
|
||||
#define XK_3270 // for XK_3270_BackTab
|
||||
#include <X11/XF86keysym.h>
|
||||
#include <X11/Xcursor/Xcursor.h>
|
||||
#include <X11/extensions/XInput2.h>
|
||||
#include <X11/keysym.h>
|
||||
|
||||
#include "include/base/cef_logging.h"
|
||||
@ -28,6 +29,17 @@ namespace client {
|
||||
|
||||
namespace {
|
||||
|
||||
// Major opcode of XInputExtension, or -1 if XInput 2.2 is not available.
|
||||
int g_xinput_extension = -1;
|
||||
|
||||
// Static BrowserWindowOsrGtk::EventFilter needs to forward touch events
|
||||
// to correct browser, so we maintain a vector of all windows.
|
||||
std::vector<BrowserWindowOsrGtk*> g_browser_windows;
|
||||
|
||||
bool IsTouchAvailable() {
|
||||
return g_xinput_extension != -1;
|
||||
}
|
||||
|
||||
int GetCefStateModifiers(guint state) {
|
||||
int modifiers = 0;
|
||||
if (state & GDK_SHIFT_MASK)
|
||||
@ -47,6 +59,20 @@ int GetCefStateModifiers(guint state) {
|
||||
return modifiers;
|
||||
}
|
||||
|
||||
int GetCefStateModifiers(XIModifierState mods, XIButtonState buttons) {
|
||||
guint state = mods.effective;
|
||||
if (buttons.mask_len >= 1) {
|
||||
if (XIMaskIsSet(buttons.mask, 1))
|
||||
state |= GDK_BUTTON1_MASK;
|
||||
if (XIMaskIsSet(buttons.mask, 2))
|
||||
state |= GDK_BUTTON2_MASK;
|
||||
if (XIMaskIsSet(buttons.mask, 3))
|
||||
state |= GDK_BUTTON3_MASK;
|
||||
}
|
||||
|
||||
return GetCefStateModifiers(state);
|
||||
}
|
||||
|
||||
// From ui/events/keycodes/keyboard_codes_posix.h.
|
||||
enum KeyboardCode {
|
||||
VKEY_BACK = 0x08,
|
||||
@ -948,9 +974,12 @@ BrowserWindowOsrGtk::BrowserWindowOsrGtk(BrowserWindow::Delegate* delegate,
|
||||
drag_drop_(false),
|
||||
device_scale_factor_(1.0f) {
|
||||
client_handler_ = new ClientHandlerOsr(this, this, startup_url);
|
||||
g_browser_windows.push_back(this);
|
||||
}
|
||||
|
||||
BrowserWindowOsrGtk::~BrowserWindowOsrGtk() {
|
||||
g_browser_windows.erase(
|
||||
std::find(g_browser_windows.begin(), g_browser_windows.end(), this));
|
||||
ScopedGdkThreadsEnter scoped_gdk_threads;
|
||||
|
||||
if (drag_trigger_event_) {
|
||||
@ -1387,6 +1416,11 @@ void BrowserWindowOsrGtk::Create(ClientWindowHandle parent_handle) {
|
||||
|
||||
// Make the GlArea visible in the parent container.
|
||||
gtk_widget_show_all(parent_handle);
|
||||
|
||||
InitializeXinput(xdisplay_);
|
||||
|
||||
if (IsTouchAvailable())
|
||||
RegisterTouch();
|
||||
}
|
||||
|
||||
// static
|
||||
@ -1640,6 +1674,108 @@ gint BrowserWindowOsrGtk::FocusEvent(GtkWidget* widget,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void BrowserWindowOsrGtk::TouchEvent(CefXIDeviceEvent event) {
|
||||
if (!browser_.get())
|
||||
return;
|
||||
|
||||
XIDeviceEvent* ev = static_cast<XIDeviceEvent*>(event);
|
||||
CefTouchEvent cef_event;
|
||||
switch (ev->evtype) {
|
||||
case XI_TouchBegin:
|
||||
cef_event.type = CEF_TET_PRESSED;
|
||||
break;
|
||||
case XI_TouchUpdate:
|
||||
cef_event.type = CEF_TET_MOVED;
|
||||
break;
|
||||
case XI_TouchEnd:
|
||||
cef_event.type = CEF_TET_RELEASED;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
cef_event.id = ev->detail;
|
||||
cef_event.x = ev->event_x;
|
||||
cef_event.y = ev->event_y;
|
||||
cef_event.radius_x = 0;
|
||||
cef_event.radius_y = 0;
|
||||
cef_event.rotation_angle = 0;
|
||||
cef_event.pressure = 0;
|
||||
cef_event.modifiers = GetCefStateModifiers(ev->mods, ev->buttons);
|
||||
|
||||
browser_->GetHost()->SendTouchEvent(cef_event);
|
||||
}
|
||||
|
||||
void BrowserWindowOsrGtk::RegisterTouch() {
|
||||
GdkWindow* glwindow = gtk_widget_get_window(glarea_);
|
||||
::Window xwindow = GDK_WINDOW_XID(glwindow);
|
||||
uint32_t bitMask = XI_TouchBeginMask | XI_TouchUpdateMask | XI_TouchEndMask;
|
||||
|
||||
XIEventMask mask;
|
||||
mask.deviceid = XIAllMasterDevices;
|
||||
mask.mask = reinterpret_cast<unsigned char*>(&bitMask);
|
||||
mask.mask_len = sizeof(bitMask);
|
||||
XISelectEvents(xdisplay_, xwindow, &mask, 1);
|
||||
}
|
||||
|
||||
// static
|
||||
GdkFilterReturn BrowserWindowOsrGtk::EventFilter(GdkXEvent* gdk_xevent,
|
||||
GdkEvent* event,
|
||||
gpointer data) {
|
||||
XEvent* xevent = static_cast<XEvent*>(gdk_xevent);
|
||||
if (xevent->type == GenericEvent &&
|
||||
xevent->xgeneric.extension == g_xinput_extension) {
|
||||
XGetEventData(xevent->xcookie.display, &xevent->xcookie);
|
||||
XIDeviceEvent* ev = static_cast<XIDeviceEvent*>(xevent->xcookie.data);
|
||||
|
||||
if (!ev)
|
||||
return GDK_FILTER_REMOVE;
|
||||
|
||||
for (BrowserWindowOsrGtk* browser_window : g_browser_windows) {
|
||||
GtkWidget* widget = browser_window->GetWindowHandle();
|
||||
::Window xwindow = GDK_WINDOW_XID(gtk_widget_get_window(widget));
|
||||
if (xwindow == ev->event) {
|
||||
browser_window->TouchEvent(ev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
XFreeEventData(xevent->xcookie.display, &xevent->xcookie);
|
||||
// Even if we didn't find a consumer for this event, we will make sure Gdk
|
||||
// doesn't attempt to process the event, since it can't parse GenericEvents
|
||||
return GDK_FILTER_REMOVE;
|
||||
}
|
||||
|
||||
return GDK_FILTER_CONTINUE;
|
||||
}
|
||||
|
||||
// static
|
||||
void BrowserWindowOsrGtk::InitializeXinput(XDisplay* xdisplay) {
|
||||
static bool initialized = false;
|
||||
if (initialized)
|
||||
return;
|
||||
initialized = true;
|
||||
|
||||
int firstEvent, firstError;
|
||||
if (XQueryExtension(xdisplay, "XInputExtension", &g_xinput_extension,
|
||||
&firstEvent, &firstError)) {
|
||||
int major = 2, minor = 2;
|
||||
// X Input Extension 2.2 is needed for multitouch events.
|
||||
if (XIQueryVersion(xdisplay, &major, &minor) == Success) {
|
||||
// Ideally we would add an event filter for each glarea_ window
|
||||
// separately, but unfortunately GDK can't parse X GenericEvents
|
||||
// which have the target window stored in different way compared
|
||||
// to other X events. That is why we add this global event filter
|
||||
// just once, and dispatch the event to correct BrowserWindowOsrGtk
|
||||
// manually.
|
||||
gdk_window_add_filter(nullptr, &BrowserWindowOsrGtk::EventFilter,
|
||||
nullptr);
|
||||
} else {
|
||||
g_xinput_extension = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool BrowserWindowOsrGtk::IsOverPopupWidget(int x, int y) const {
|
||||
const CefRect& rc = renderer_.popup_rect();
|
||||
int popup_right = rc.x + rc.width;
|
||||
|
@ -20,6 +20,8 @@ namespace client {
|
||||
class BrowserWindowOsrGtk : public BrowserWindow,
|
||||
public ClientHandlerOsr::OsrDelegate {
|
||||
public:
|
||||
typedef void* CefXIDeviceEvent;
|
||||
|
||||
// Constructor may be called on any thread.
|
||||
// |delegate| must outlive this object.
|
||||
BrowserWindowOsrGtk(BrowserWindow::Delegate* delegate,
|
||||
@ -114,6 +116,9 @@ class BrowserWindowOsrGtk : public BrowserWindow,
|
||||
GdkEventFocus* event,
|
||||
BrowserWindowOsrGtk* self);
|
||||
|
||||
void TouchEvent(CefXIDeviceEvent event);
|
||||
void RegisterTouch();
|
||||
|
||||
bool IsOverPopupWidget(int x, int y) const;
|
||||
int GetPopupXOffset() const;
|
||||
int GetPopupYOffset() const;
|
||||
@ -166,6 +171,10 @@ class BrowserWindowOsrGtk : public BrowserWindow,
|
||||
guint info,
|
||||
guint time,
|
||||
BrowserWindowOsrGtk* self);
|
||||
static GdkFilterReturn EventFilter(GdkXEvent* gdk_xevent,
|
||||
GdkEvent* event,
|
||||
gpointer data);
|
||||
static void InitializeXinput(XDisplay* xdisplay);
|
||||
|
||||
XDisplay* xdisplay_;
|
||||
|
||||
|
@ -33,7 +33,7 @@ CefTextInputClientOSRMac* GetInputClientFromContext(
|
||||
} // namespace
|
||||
|
||||
@interface BrowserOpenGLView
|
||||
: NSOpenGLView<NSDraggingSource, NSDraggingDestination, NSAccessibility> {
|
||||
: NSOpenGLView <NSDraggingSource, NSDraggingDestination, NSAccessibility> {
|
||||
@private
|
||||
NSTrackingArea* tracking_area_;
|
||||
client::BrowserWindowOsrMac* browser_window_;
|
||||
@ -238,8 +238,8 @@ NSPoint ConvertPointFromWindowToScreen(NSWindow* window, NSPoint point) {
|
||||
point = [self convertPointToBackingInternal:point];
|
||||
|
||||
if (!isUp) {
|
||||
was_last_mouse_down_on_view_ =
|
||||
![self isOverPopupWidgetX:point.x andY:point.y];
|
||||
was_last_mouse_down_on_view_ = ![self isOverPopupWidgetX:point.x
|
||||
andY:point.y];
|
||||
} else if (was_last_mouse_down_on_view_ &&
|
||||
[self isOverPopupWidgetX:point.x andY:point.y] &&
|
||||
([self getPopupXOffset] || [self getPopupYOffset])) {
|
||||
@ -359,6 +359,110 @@ NSPoint ConvertPointFromWindowToScreen(NSWindow* window, NSPoint point) {
|
||||
[client HandleKeyEventAfterTextInputClient:keyEvent];
|
||||
}
|
||||
}
|
||||
|
||||
// Check for Caps lock and Toggle Touch Emulation
|
||||
if (client::MainContext::Get()->TouchEventsEnabled())
|
||||
[self toggleTouchEmulation:event];
|
||||
}
|
||||
|
||||
// OSX does not have touch screens, so we emulate it by mapping multitouch
|
||||
// events on TrackPad to Touch Events on Screen. To ensure it does not
|
||||
// interfere with other Trackpad events, this mapping is only enabled if
|
||||
// touch-events=enabled commandline is passed and caps lock key is on.
|
||||
- (void)toggleTouchEmulation:(NSEvent*)event {
|
||||
if ([event type] == NSFlagsChanged && [event keyCode] == 0x39) {
|
||||
NSUInteger flags = [event modifierFlags];
|
||||
BOOL touch_enabled = flags & NSAlphaShiftKeyMask ? YES : NO;
|
||||
[self setAcceptsTouchEvents:touch_enabled];
|
||||
}
|
||||
}
|
||||
|
||||
- (cef_touch_event_type_t)getTouchPhase:(NSTouchPhase)phase {
|
||||
cef_touch_event_type_t event_type = CEF_TET_RELEASED;
|
||||
switch (phase) {
|
||||
case NSTouchPhaseBegan:
|
||||
event_type = CEF_TET_PRESSED;
|
||||
break;
|
||||
case NSTouchPhaseMoved:
|
||||
event_type = CEF_TET_MOVED;
|
||||
break;
|
||||
case NSTouchPhaseEnded:
|
||||
event_type = CEF_TET_RELEASED;
|
||||
break;
|
||||
case NSTouchPhaseCancelled:
|
||||
event_type = CEF_TET_CANCELLED;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return event_type;
|
||||
}
|
||||
|
||||
// Translate NSTouch events to CefTouchEvents and send to browser.
|
||||
- (void)sendTouchEvent:(NSEvent*)event touchPhase:(NSTouchPhase)phase {
|
||||
int modifiers = [self getModifiersForEvent:event];
|
||||
CefRefPtr<CefBrowser> browser = [self getBrowser];
|
||||
|
||||
NSSet* touches = [event touchesMatchingPhase:phase inView:self];
|
||||
|
||||
for (NSTouch* touch in touches) {
|
||||
// Convert NSTouch to CefTouchEvent.
|
||||
CefTouchEvent touch_event;
|
||||
|
||||
// NSTouch.identity is unique during the life of the touch
|
||||
touch_event.id = touch.identity.hash;
|
||||
touch_event.type = [self getTouchPhase:phase];
|
||||
|
||||
NSPoint scaled_pos = [touch normalizedPosition];
|
||||
NSSize view_size = [self bounds].size;
|
||||
|
||||
// Map point on Touch Device to View coordinates.
|
||||
NSPoint touch_point = NSMakePoint(scaled_pos.x * view_size.width,
|
||||
scaled_pos.y * view_size.height);
|
||||
|
||||
NSPoint contentLocal = [self convertPoint:touch_point fromView:nil];
|
||||
NSPoint point;
|
||||
point.x = contentLocal.x;
|
||||
point.y = [self frame].size.height - contentLocal.y; // Flip y.
|
||||
|
||||
// Convert to device coordinates.
|
||||
point = [self convertPointToBackingInternal:point];
|
||||
|
||||
int device_x = point.x;
|
||||
int device_y = point.y;
|
||||
|
||||
const float device_scale_factor = [self getDeviceScaleFactor];
|
||||
// Convert to browser view coordinates.
|
||||
touch_event.x = client::DeviceToLogical(device_x, device_scale_factor);
|
||||
touch_event.y = client::DeviceToLogical(device_y, device_scale_factor);
|
||||
|
||||
touch_event.radius_x = 0;
|
||||
touch_event.radius_y = 0;
|
||||
|
||||
touch_event.rotation_angle = 0;
|
||||
touch_event.pressure = 0;
|
||||
|
||||
touch_event.modifiers = modifiers;
|
||||
|
||||
// Notify the browser of touch event.
|
||||
browser->GetHost()->SendTouchEvent(touch_event);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)touchesBeganWithEvent:(NSEvent*)event {
|
||||
[self sendTouchEvent:event touchPhase:NSTouchPhaseBegan];
|
||||
}
|
||||
|
||||
- (void)touchesMovedWithEvent:(NSEvent*)event {
|
||||
[self sendTouchEvent:event touchPhase:NSTouchPhaseMoved];
|
||||
}
|
||||
|
||||
- (void)touchesEndedWithEvent:(NSEvent*)event {
|
||||
[self sendTouchEvent:event touchPhase:NSTouchPhaseEnded];
|
||||
}
|
||||
|
||||
- (void)touchesCancelledWithEvent:(NSEvent*)event {
|
||||
[self sendTouchEvent:event touchPhase:NSTouchPhaseCancelled];
|
||||
}
|
||||
|
||||
- (void)keyUp:(NSEvent*)event {
|
||||
@ -490,7 +594,7 @@ NSPoint ConvertPointFromWindowToScreen(NSWindow* window, NSPoint point) {
|
||||
browser->GetFocusedFrame()->Paste();
|
||||
}
|
||||
|
||||
- (void) delete:(id)sender {
|
||||
- (void)delete:(id)sender {
|
||||
CefRefPtr<CefBrowser> browser = [self getBrowser];
|
||||
if (browser.get())
|
||||
browser->GetFocusedFrame()->Delete();
|
||||
|
@ -3,6 +3,7 @@
|
||||
// can be found in the LICENSE file.
|
||||
|
||||
#include "tests/cefclient/browser/client_browser.h"
|
||||
#include "tests/cefclient/browser/main_context.h"
|
||||
|
||||
#include "include/cef_command_line.h"
|
||||
#include "include/cef_crash_util.h"
|
||||
@ -39,6 +40,14 @@ class ClientBrowserDelegate : public ClientAppBrowser::Delegate {
|
||||
}
|
||||
}
|
||||
|
||||
void OnBeforeCommandLineProcessing(
|
||||
CefRefPtr<ClientAppBrowser> app,
|
||||
CefRefPtr<CefCommandLine> command_line) OVERRIDE {
|
||||
// Append Chromium command line parameters if touch events are enabled
|
||||
if (client::MainContext::Get()->TouchEventsEnabled())
|
||||
command_line->AppendSwitchWithValue("touch-events", "enabled");
|
||||
}
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(ClientBrowserDelegate);
|
||||
IMPLEMENT_REFCOUNTING(ClientBrowserDelegate);
|
||||
|
@ -44,6 +44,9 @@ class MainContext {
|
||||
// Returns true if windowless (off-screen) rendering will be used.
|
||||
virtual bool UseWindowlessRendering() = 0;
|
||||
|
||||
// Returns true if touch events are enabled.
|
||||
virtual bool TouchEventsEnabled() = 0;
|
||||
|
||||
// Populate |settings| based on command-line arguments.
|
||||
virtual void PopulateSettings(CefSettings* settings) = 0;
|
||||
virtual void PopulateBrowserSettings(CefBrowserSettings* settings) = 0;
|
||||
|
@ -163,6 +163,10 @@ bool MainContextImpl::UseWindowlessRendering() {
|
||||
return use_windowless_rendering_;
|
||||
}
|
||||
|
||||
bool MainContextImpl::TouchEventsEnabled() {
|
||||
return command_line_->GetSwitchValue("touch-events") == "enabled";
|
||||
}
|
||||
|
||||
void MainContextImpl::PopulateSettings(CefSettings* settings) {
|
||||
#if defined(OS_WIN) || defined(OS_LINUX)
|
||||
settings->multi_threaded_message_loop =
|
||||
|
@ -29,6 +29,7 @@ class MainContextImpl : public MainContext {
|
||||
cef_color_t GetBackgroundColor() OVERRIDE;
|
||||
bool UseViews() OVERRIDE;
|
||||
bool UseWindowlessRendering() OVERRIDE;
|
||||
bool TouchEventsEnabled() OVERRIDE;
|
||||
void PopulateSettings(CefSettings* settings) OVERRIDE;
|
||||
void PopulateBrowserSettings(CefBrowserSettings* settings) OVERRIDE;
|
||||
void PopulateOsrSettings(OsrRendererSettings* settings) OVERRIDE;
|
||||
@ -70,6 +71,7 @@ class MainContextImpl : public MainContext {
|
||||
bool use_windowless_rendering_;
|
||||
int windowless_frame_rate_;
|
||||
bool use_views_;
|
||||
bool touch_events_enabled_;
|
||||
|
||||
scoped_ptr<RootWindowManager> root_window_manager_;
|
||||
|
||||
|
@ -27,6 +27,29 @@ namespace {
|
||||
|
||||
const wchar_t kWndClass[] = L"Client_OsrWindow";
|
||||
|
||||
// Helper funtion to check if it is Windows8 or greater.
|
||||
// https://msdn.microsoft.com/en-us/library/ms724833(v=vs.85).aspx
|
||||
inline BOOL IsWindows_8_Or_Newer() {
|
||||
OSVERSIONINFOEX osvi = {0};
|
||||
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
|
||||
osvi.dwMajorVersion = 6;
|
||||
osvi.dwMinorVersion = 2;
|
||||
DWORDLONG dwlConditionMask = 0;
|
||||
VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
|
||||
VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, VER_GREATER_EQUAL);
|
||||
return ::VerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION,
|
||||
dwlConditionMask);
|
||||
}
|
||||
|
||||
// Helper function to detect mouse messages coming from emulation of touch
|
||||
// events. These should be ignored.
|
||||
bool IsMouseEventFromTouch(UINT message) {
|
||||
#define MOUSEEVENTF_FROMTOUCH 0xFF515700
|
||||
return (message >= WM_MOUSEFIRST) && (message <= WM_MOUSELAST) &&
|
||||
(GetMessageExtraInfo() & MOUSEEVENTF_FROMTOUCH) ==
|
||||
MOUSEEVENTF_FROMTOUCH;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
OsrWindowWin::OsrWindowWin(Delegate* delegate,
|
||||
@ -256,6 +279,10 @@ void OsrWindowWin::Create(HWND parent_hwnd, const RECT& rect) {
|
||||
|
||||
ime_handler_.reset(new OsrImeHandlerWin(hwnd_));
|
||||
|
||||
// Enable Touch Events if requested
|
||||
if (client::MainContext::Get()->TouchEventsEnabled())
|
||||
RegisterTouchWindow(hwnd_, 0);
|
||||
|
||||
// Notify the window owner.
|
||||
NotifyNativeWindowCreated(hwnd_);
|
||||
}
|
||||
@ -476,6 +503,15 @@ LRESULT CALLBACK OsrWindowWin::OsrWndProc(HWND hWnd,
|
||||
// Don't erase the background.
|
||||
return 0;
|
||||
|
||||
// If your application does not require Win7 support, please do consider
|
||||
// using WM_POINTER* messages instead of WM_TOUCH. WM_POINTER are more
|
||||
// intutive, complete and simpler to code.
|
||||
// https://msdn.microsoft.com/en-us/library/hh454903(v=vs.85).aspx
|
||||
case WM_TOUCH:
|
||||
if (self->OnTouchEvent(message, wParam, lParam))
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case WM_NCDESTROY:
|
||||
// Clear the reference to |self|.
|
||||
SetUserDataPtr(hWnd, NULL);
|
||||
@ -487,6 +523,9 @@ LRESULT CALLBACK OsrWindowWin::OsrWndProc(HWND hWnd,
|
||||
}
|
||||
|
||||
void OsrWindowWin::OnMouseEvent(UINT message, WPARAM wParam, LPARAM lParam) {
|
||||
if (IsMouseEventFromTouch(message))
|
||||
return;
|
||||
|
||||
CefRefPtr<CefBrowserHost> browser_host;
|
||||
if (browser_)
|
||||
browser_host = browser_->GetHost();
|
||||
@ -733,6 +772,63 @@ bool OsrWindowWin::OnEraseBkgnd() {
|
||||
return (browser_ == NULL);
|
||||
}
|
||||
|
||||
bool OsrWindowWin::OnTouchEvent(UINT message, WPARAM wParam, LPARAM lParam) {
|
||||
// Handle touch events on Windows.
|
||||
int num_points = LOWORD(wParam);
|
||||
// Chromium only supports upto 16 touch points.
|
||||
if (num_points < 0 || num_points > 16)
|
||||
return false;
|
||||
std::unique_ptr<TOUCHINPUT[]> input(new TOUCHINPUT[num_points]);
|
||||
if (GetTouchInputInfo(reinterpret_cast<HTOUCHINPUT>(lParam), num_points,
|
||||
input.get(), sizeof(TOUCHINPUT))) {
|
||||
CefTouchEvent touch_event;
|
||||
for (int i = 0; i < num_points; ++i) {
|
||||
POINT point;
|
||||
point.x = TOUCH_COORD_TO_PIXEL(input[i].x);
|
||||
point.y = TOUCH_COORD_TO_PIXEL(input[i].y);
|
||||
|
||||
if (!IsWindows_8_Or_Newer()) {
|
||||
// Windows 7 sends touch events for touches in the non-client area,
|
||||
// whereas Windows 8 does not. In order to unify the behaviour, always
|
||||
// ignore touch events in the non-client area.
|
||||
LPARAM l_param_ht = MAKELPARAM(point.x, point.y);
|
||||
LRESULT hittest = SendMessage(hwnd_, WM_NCHITTEST, 0, l_param_ht);
|
||||
if (hittest != HTCLIENT)
|
||||
return false;
|
||||
}
|
||||
|
||||
ScreenToClient(hwnd_, &point);
|
||||
touch_event.x = DeviceToLogical(point.x, device_scale_factor_);
|
||||
touch_event.y = DeviceToLogical(point.y, device_scale_factor_);
|
||||
|
||||
// Touch point identifier stays consistent in a touch contact sequence
|
||||
touch_event.id = input[i].dwID;
|
||||
|
||||
if (input[i].dwFlags & TOUCHEVENTF_DOWN) {
|
||||
touch_event.type = CEF_TET_PRESSED;
|
||||
} else if (input[i].dwFlags & TOUCHEVENTF_MOVE) {
|
||||
touch_event.type = CEF_TET_MOVED;
|
||||
} else if (input[i].dwFlags & TOUCHEVENTF_UP) {
|
||||
touch_event.type = CEF_TET_RELEASED;
|
||||
}
|
||||
|
||||
touch_event.radius_x = 0;
|
||||
touch_event.radius_y = 0;
|
||||
touch_event.rotation_angle = 0;
|
||||
touch_event.pressure = 0;
|
||||
touch_event.modifiers = 0;
|
||||
|
||||
// Notify the browser of touch event
|
||||
if (browser_)
|
||||
browser_->GetHost()->SendTouchEvent(touch_event);
|
||||
}
|
||||
CloseTouchInputHandle(reinterpret_cast<HTOUCHINPUT>(lParam));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool OsrWindowWin::IsOverPopupWidget(int x, int y) const {
|
||||
if (!render_handler_)
|
||||
return false;
|
||||
|
@ -93,6 +93,7 @@ class OsrWindowWin
|
||||
void OnKeyEvent(UINT message, WPARAM wParam, LPARAM lParam);
|
||||
void OnPaint();
|
||||
bool OnEraseBkgnd();
|
||||
bool OnTouchEvent(UINT message, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
void OnIMESetContext(UINT message, WPARAM wParam, LPARAM lParam);
|
||||
void OnIMEStartComposition();
|
||||
|
@ -36,6 +36,7 @@
|
||||
<li><a href="urlrequest">CefURLRequest</a></li>
|
||||
<li><a href="xmlhttprequest">XMLHttpRequest</a></li>
|
||||
<li><a href="javascript:window.print();">Print this page with "javascript:window.print();"</a></li>
|
||||
<li><a href="https://patrickhlauke.github.io/touch">Touch Feature Tests</a> - requires "touch-events=enabled" flag (and CAPS LOCK on Mac for Trackpad simulation) </li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -160,7 +160,14 @@ enum OSRTestType {
|
||||
OSR_TEST_TEXT_SELECTION_CHANGE,
|
||||
// clicking on text input will call OnVirtualKeyboardRequested
|
||||
OSR_TEST_VIRTUAL_KEYBOARD,
|
||||
|
||||
// touchStart event is triggered and contains the touch point count
|
||||
OSR_TEST_TOUCH_START,
|
||||
// touchMove event is triggered and contains the changed touch points
|
||||
OSR_TEST_TOUCH_MOVE,
|
||||
// touchEnd is triggered on completion
|
||||
OSR_TEST_TOUCH_END,
|
||||
// touchCancel is triggered on dismissing
|
||||
OSR_TEST_TOUCH_CANCEL,
|
||||
// Define the range for popup tests.
|
||||
OSR_TEST_POPUP_FIRST = OSR_TEST_POPUP_PAINT,
|
||||
OSR_TEST_POPUP_LAST = OSR_TEST_POPUP_SCROLL_INSIDE,
|
||||
@ -177,7 +184,8 @@ class OSRTestHandler : public RoutingTestHandler,
|
||||
scale_factor_(scale_factor),
|
||||
event_count_(0),
|
||||
event_total_(1),
|
||||
started_(false) {}
|
||||
started_(false),
|
||||
touch_state_(CEF_TET_CANCELLED) {}
|
||||
|
||||
// TestHandler methods
|
||||
void RunTest() override {
|
||||
@ -262,11 +270,58 @@ class OSRTestHandler : public RoutingTestHandler,
|
||||
EXPECT_STREQ(messageStr.c_str(), "osrdrop");
|
||||
DestroySucceededTestSoon();
|
||||
break;
|
||||
case OSR_TEST_TOUCH_START:
|
||||
case OSR_TEST_TOUCH_MOVE:
|
||||
case OSR_TEST_TOUCH_END:
|
||||
case OSR_TEST_TOUCH_CANCEL: {
|
||||
switch (touch_state_) {
|
||||
case CEF_TET_CANCELLED: {
|
||||
// The first message expected is touchstart.
|
||||
// We expect multitouch, so touches length should be 2.
|
||||
// Ignore intermediate touch start events.
|
||||
if (messageStr == "osrtouchstart1")
|
||||
break;
|
||||
EXPECT_STREQ(messageStr.c_str(), "osrtouchstart2");
|
||||
// Close Touch Start Tests.
|
||||
if (test_type_ == OSR_TEST_TOUCH_START) {
|
||||
DestroySucceededTestSoon();
|
||||
touch_state_ = CEF_TET_RELEASED;
|
||||
} else {
|
||||
touch_state_ = CEF_TET_PRESSED;
|
||||
}
|
||||
} break;
|
||||
case CEF_TET_PRESSED: {
|
||||
// Touch Move include the touches that changed, should be 2.
|
||||
EXPECT_STREQ(messageStr.c_str(), "osrtouchmove2");
|
||||
if (test_type_ == OSR_TEST_TOUCH_MOVE) {
|
||||
DestroySucceededTestSoon();
|
||||
touch_state_ = CEF_TET_RELEASED;
|
||||
} else {
|
||||
touch_state_ = CEF_TET_MOVED;
|
||||
}
|
||||
} break;
|
||||
case CEF_TET_MOVED: {
|
||||
// There might be multiple touchmove events, ignore.
|
||||
if (messageStr != "osrtouchmove2") {
|
||||
if (test_type_ == OSR_TEST_TOUCH_END) {
|
||||
EXPECT_STREQ(messageStr.c_str(), "osrtouchend");
|
||||
DestroySucceededTestSoon();
|
||||
touch_state_ = CEF_TET_RELEASED;
|
||||
} else if (test_type_ == OSR_TEST_TOUCH_CANCEL) {
|
||||
EXPECT_STREQ(messageStr.c_str(), "osrtouchcancel");
|
||||
DestroySucceededTestSoon();
|
||||
touch_state_ = CEF_TET_RELEASED;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
// Intentionally left blank
|
||||
break;
|
||||
}
|
||||
|
||||
callback->Success("");
|
||||
return true;
|
||||
}
|
||||
@ -960,6 +1015,50 @@ class OSRTestHandler : public RoutingTestHandler,
|
||||
1);
|
||||
}
|
||||
} break;
|
||||
case OSR_TEST_TOUCH_START:
|
||||
case OSR_TEST_TOUCH_MOVE:
|
||||
case OSR_TEST_TOUCH_END:
|
||||
case OSR_TEST_TOUCH_CANCEL: {
|
||||
// We trigger a valid Touch workflow sequence and close the tests
|
||||
// at seperate points for the 4 cases
|
||||
if (StartTest()) {
|
||||
const CefRect& touchdiv = GetElementBounds("touchdiv");
|
||||
// click inside edit box so that text could be entered
|
||||
CefTouchEvent touch_event1;
|
||||
touch_event1.id = 0;
|
||||
touch_event1.x = MiddleX(touchdiv) - 45;
|
||||
touch_event1.y = MiddleY(touchdiv);
|
||||
touch_event1.modifiers = 0;
|
||||
touch_event1.type = CEF_TET_PRESSED;
|
||||
|
||||
CefTouchEvent touch_event2;
|
||||
touch_event2.id = 1;
|
||||
touch_event2.x = MiddleX(touchdiv) + 45;
|
||||
touch_event2.y = MiddleY(touchdiv);
|
||||
touch_event2.modifiers = 0;
|
||||
touch_event2.type = CEF_TET_PRESSED;
|
||||
|
||||
browser->GetHost()->SendTouchEvent(touch_event1);
|
||||
browser->GetHost()->SendTouchEvent(touch_event2);
|
||||
|
||||
// Move the Touch fingers closer
|
||||
touch_event1.type = touch_event2.type = CEF_TET_MOVED;
|
||||
for (size_t i = 0; i < 40; i++) {
|
||||
touch_event1.x++;
|
||||
touch_event2.x--;
|
||||
browser->GetHost()->SendTouchEvent(touch_event1);
|
||||
browser->GetHost()->SendTouchEvent(touch_event2);
|
||||
}
|
||||
|
||||
// Now release the Touch fingers or cancel them
|
||||
if (test_type_ == OSR_TEST_TOUCH_CANCEL)
|
||||
touch_event1.type = touch_event2.type = CEF_TET_CANCELLED;
|
||||
else
|
||||
touch_event1.type = touch_event2.type = CEF_TET_RELEASED;
|
||||
browser->GetHost()->SendTouchEvent(touch_event1);
|
||||
browser->GetHost()->SendTouchEvent(touch_event2);
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -1349,6 +1448,7 @@ class OSRTestHandler : public RoutingTestHandler,
|
||||
int event_count_;
|
||||
int event_total_;
|
||||
bool started_;
|
||||
cef_touch_event_type_t touch_state_;
|
||||
TrackCallback got_update_cursor_;
|
||||
TrackCallback got_navigation_focus_event_;
|
||||
TrackCallback got_system_focus_event_;
|
||||
@ -1441,3 +1541,11 @@ OSR_TEST(IMECancelComposition2x, OSR_TEST_IME_CANCEL_COMPOSITION, 2.0f);
|
||||
OSR_TEST(TextSelectionChanged, OSR_TEST_TEXT_SELECTION_CHANGE, 1.0f);
|
||||
OSR_TEST(TextSelectionChanged2x, OSR_TEST_TEXT_SELECTION_CHANGE, 2.0f);
|
||||
OSR_TEST(VirtualKeyboard, OSR_TEST_VIRTUAL_KEYBOARD, 1.0f);
|
||||
OSR_TEST(TouchStart, OSR_TEST_TOUCH_START, 1.0f);
|
||||
OSR_TEST(TouchStart2X, OSR_TEST_TOUCH_START, 2.0f);
|
||||
OSR_TEST(TouchMove, OSR_TEST_TOUCH_MOVE, 1.0f);
|
||||
OSR_TEST(TouchMove2X, OSR_TEST_TOUCH_MOVE, 2.0f);
|
||||
OSR_TEST(TouchEnd, OSR_TEST_TOUCH_END, 1.0f);
|
||||
OSR_TEST(TouchEnd2X, OSR_TEST_TOUCH_END, 2.0f);
|
||||
OSR_TEST(TouchCancel, OSR_TEST_TOUCH_CANCEL, 1.0f);
|
||||
OSR_TEST(TouchCancel2X, OSR_TEST_TOUCH_CANCEL, 2.0f);
|
||||
|
@ -25,6 +25,13 @@
|
||||
left: 7px;
|
||||
opacity: 0.4;
|
||||
}
|
||||
#touchdiv {
|
||||
width: 100px;
|
||||
height: 50px;
|
||||
background-color: red;
|
||||
float: left;
|
||||
margin-left: 10px;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
function getElement(id) { return document.getElementById(id); }
|
||||
@ -53,6 +60,7 @@
|
||||
elems.push(getElementBounds('btnnavigate'));
|
||||
elems.push(getElementBounds('dropdiv'));
|
||||
elems.push(getElementBounds('dragdiv'));
|
||||
elems.push(getElementBounds('touchdiv'));
|
||||
|
||||
if (window.testQuery)
|
||||
window.testQuery({request: JSON.stringify(param)});
|
||||
@ -115,6 +123,21 @@
|
||||
selection.removeAllRanges();
|
||||
selection.addRange(range);
|
||||
}
|
||||
|
||||
function onTouchEvent(ev) {
|
||||
var param = 'osr' + ev.type;
|
||||
// For Touch start also include touch points.
|
||||
if (event.type == "touchstart")
|
||||
param += ev.touches.length;
|
||||
// For Touch Move include the touches that changed.
|
||||
if (event.type == "touchmove")
|
||||
param += ev.changedTouches.length;
|
||||
|
||||
// Results in a call to the OnQuery method in os_rendering_unittest.cc.
|
||||
if (window.testQuery)
|
||||
window.testQuery({request: param});
|
||||
}
|
||||
|
||||
</script>
|
||||
<body onfocus='onEventTest(event)' onblur='onEventTest(event)' onload='load();'>
|
||||
<h1 id='LI00' onclick="onEventTest(event)">
|
||||
@ -146,12 +169,15 @@
|
||||
<li id='LI11' onclick='selectText(event)'>SELECTED_TEXT_RANGE</li>
|
||||
<li><input id='email' type='text' size=10 inputmode='email'></li>
|
||||
</ol>
|
||||
|
||||
<div class="dropdiv" id="dropdiv" ondrop="drop(event)" ondragover="allowDrop(event)">
|
||||
<span id="draghere">Drag here</span>
|
||||
</div>
|
||||
<div class="dropdiv">
|
||||
<div id="dragdiv" draggable="true" ondragstart="drag(event)"></div>
|
||||
</div>
|
||||
<div id="touchdiv" ontouchstart="onTouchEvent(event)" ontouchend="onTouchEvent(event)" ontouchmove="onTouchEvent(event)" ontouchcancel="onTouchEvent(event)">
|
||||
</div>
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
|
Loading…
x
Reference in New Issue
Block a user