0

Enable pinch-zoom telemetry on Mac

This change adds a SyntheticGestureTargetMac which is able to interpret the
touches sent from telemetry's pinch simulator and convert these into trackpad
zoom gestures.

BUG=
CQ_EXTRA_TRYBOTS=tryserver.chromium.perf:linux_perf_bisect;tryserver.chromium.perf:mac_10_10_perf_bisect;tryserver.chromium.perf:win_perf_bisect;tryserver.chromium.perf:android_nexus5_perf_bisect

Review URL: https://codereview.chromium.org/1349813002

Cr-Commit-Position: refs/heads/master@{#350316}
This commit is contained in:
ericrk
2015-09-22 23:12:11 -07:00
committed by Commit bot
parent f691b53b92
commit ecb20ba696
14 changed files with 887 additions and 228 deletions

@ -13,6 +13,8 @@
#include "content/browser/renderer_host/input/synthetic_smooth_move_gesture.h"
#include "content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h"
#include "content/browser/renderer_host/input/synthetic_tap_gesture.h"
#include "content/browser/renderer_host/input/synthetic_touchpad_pinch_gesture.h"
#include "content/browser/renderer_host/input/synthetic_touchscreen_pinch_gesture.h"
#include "content/browser/renderer_host/render_widget_host_delegate.h"
#include "content/common/input/synthetic_pinch_gesture_params.h"
#include "content/common/input/synthetic_smooth_drag_gesture_params.h"
@ -218,7 +220,8 @@ class MockDragMouseTarget : public MockMoveGestureTarget {
gfx::PointF start_, last_mouse_point_;
};
class MockSyntheticPinchTouchTarget : public MockSyntheticGestureTarget {
class MockSyntheticTouchscreenPinchTouchTarget
: public MockSyntheticGestureTarget {
public:
enum ZoomDirection {
ZOOM_DIRECTION_UNKNOWN,
@ -226,12 +229,12 @@ class MockSyntheticPinchTouchTarget : public MockSyntheticGestureTarget {
ZOOM_OUT
};
MockSyntheticPinchTouchTarget()
MockSyntheticTouchscreenPinchTouchTarget()
: initial_pointer_distance_(0),
last_pointer_distance_(0),
zoom_direction_(ZOOM_DIRECTION_UNKNOWN),
started_(false) {}
~MockSyntheticPinchTouchTarget() override {}
~MockSyntheticTouchscreenPinchTouchTarget() override {}
void DispatchInputEventToPlatform(const WebInputEvent& event) override {
ASSERT_TRUE(WebInputEvent::isTouchEventType(event.type));
@ -271,6 +274,11 @@ class MockSyntheticPinchTouchTarget : public MockSyntheticGestureTarget {
}
}
SyntheticGestureParams::GestureSourceType
GetDefaultSyntheticGestureSourceType() const override {
return SyntheticGestureParams::TOUCH_INPUT;
}
ZoomDirection zoom_direction() const { return zoom_direction_; }
float ComputeScaleFactor() const {
@ -305,6 +313,67 @@ class MockSyntheticPinchTouchTarget : public MockSyntheticGestureTarget {
bool started_;
};
class MockSyntheticTouchpadPinchTouchTarget
: public MockSyntheticGestureTarget {
public:
enum ZoomDirection { ZOOM_DIRECTION_UNKNOWN, ZOOM_IN, ZOOM_OUT };
MockSyntheticTouchpadPinchTouchTarget()
: zoom_direction_(ZOOM_DIRECTION_UNKNOWN),
started_(false),
ended_(false),
scale_factor_(1.0f) {}
~MockSyntheticTouchpadPinchTouchTarget() override {}
void DispatchInputEventToPlatform(const WebInputEvent& event) override {
EXPECT_TRUE(WebInputEvent::isGestureEventType(event.type));
const blink::WebGestureEvent& gesture_event =
static_cast<const blink::WebGestureEvent&>(event);
if (gesture_event.type == WebInputEvent::GesturePinchBegin) {
EXPECT_FALSE(started_);
EXPECT_FALSE(ended_);
started_ = true;
} else if (gesture_event.type == WebInputEvent::GesturePinchEnd) {
EXPECT_TRUE(started_);
EXPECT_FALSE(ended_);
ended_ = true;
} else {
EXPECT_EQ(WebInputEvent::GesturePinchUpdate, gesture_event.type);
EXPECT_TRUE(started_);
EXPECT_FALSE(ended_);
const float scale = gesture_event.data.pinchUpdate.scale;
if (scale != 1.0f) {
if (zoom_direction_ == ZOOM_DIRECTION_UNKNOWN) {
zoom_direction_ = scale > 1.0f ? ZOOM_IN : ZOOM_OUT;
} else if (zoom_direction_ == ZOOM_IN) {
EXPECT_GT(scale, 1.0f);
} else {
EXPECT_EQ(ZOOM_OUT, zoom_direction_);
EXPECT_LT(scale, 1.0f);
}
scale_factor_ *= scale;
}
}
}
SyntheticGestureParams::GestureSourceType
GetDefaultSyntheticGestureSourceType() const override {
return SyntheticGestureParams::MOUSE_INPUT;
}
ZoomDirection zoom_direction() const { return zoom_direction_; }
float scale_factor() const { return scale_factor_; }
private:
ZoomDirection zoom_direction_;
bool started_;
bool ended_;
float scale_factor_;
};
class MockSyntheticTapGestureTarget : public MockSyntheticGestureTarget {
public:
MockSyntheticTapGestureTarget() : state_(NOT_STARTED) {}
@ -1100,8 +1169,143 @@ TEST_F(SyntheticGestureControllerTest,
gesture->ForwardInputEvents(timestamp, target_);
}
TEST_F(SyntheticGestureControllerTest, PinchGestureTouchZoomIn) {
CreateControllerAndTarget<MockSyntheticPinchTouchTarget>();
TEST_F(SyntheticGestureControllerTest,
TouchscreenTouchpadPinchGestureTouchZoomIn) {
CreateControllerAndTarget<MockSyntheticTouchscreenPinchTouchTarget>();
SyntheticPinchGestureParams params;
params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;
params.scale_factor = 2.3f;
params.anchor.SetPoint(54, 89);
scoped_ptr<SyntheticTouchscreenPinchGesture> gesture(
new SyntheticTouchscreenPinchGesture(params));
QueueSyntheticGesture(gesture.Pass());
FlushInputUntilComplete();
MockSyntheticTouchscreenPinchTouchTarget* pinch_target =
static_cast<MockSyntheticTouchscreenPinchTouchTarget*>(target_);
EXPECT_EQ(1, num_success_);
EXPECT_EQ(0, num_failure_);
EXPECT_EQ(pinch_target->zoom_direction(),
MockSyntheticTouchscreenPinchTouchTarget::ZOOM_IN);
EXPECT_FLOAT_EQ(params.scale_factor, pinch_target->ComputeScaleFactor());
}
TEST_F(SyntheticGestureControllerTest,
TouchscreenTouchpadPinchGestureTouchZoomOut) {
CreateControllerAndTarget<MockSyntheticTouchscreenPinchTouchTarget>();
SyntheticPinchGestureParams params;
params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;
params.scale_factor = 0.4f;
params.anchor.SetPoint(-12, 93);
scoped_ptr<SyntheticTouchscreenPinchGesture> gesture(
new SyntheticTouchscreenPinchGesture(params));
QueueSyntheticGesture(gesture.Pass());
FlushInputUntilComplete();
MockSyntheticTouchscreenPinchTouchTarget* pinch_target =
static_cast<MockSyntheticTouchscreenPinchTouchTarget*>(target_);
EXPECT_EQ(1, num_success_);
EXPECT_EQ(0, num_failure_);
EXPECT_EQ(pinch_target->zoom_direction(),
MockSyntheticTouchscreenPinchTouchTarget::ZOOM_OUT);
EXPECT_FLOAT_EQ(params.scale_factor, pinch_target->ComputeScaleFactor());
}
TEST_F(SyntheticGestureControllerTest,
TouchscreenTouchpadPinchGestureTouchNoScaling) {
CreateControllerAndTarget<MockSyntheticTouchscreenPinchTouchTarget>();
SyntheticPinchGestureParams params;
params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;
params.scale_factor = 1.0f;
scoped_ptr<SyntheticTouchscreenPinchGesture> gesture(
new SyntheticTouchscreenPinchGesture(params));
QueueSyntheticGesture(gesture.Pass());
FlushInputUntilComplete();
MockSyntheticTouchscreenPinchTouchTarget* pinch_target =
static_cast<MockSyntheticTouchscreenPinchTouchTarget*>(target_);
EXPECT_EQ(1, num_success_);
EXPECT_EQ(0, num_failure_);
EXPECT_EQ(pinch_target->zoom_direction(),
MockSyntheticTouchscreenPinchTouchTarget::ZOOM_DIRECTION_UNKNOWN);
EXPECT_EQ(params.scale_factor, pinch_target->ComputeScaleFactor());
}
TEST_F(SyntheticGestureControllerTest, TouchpadPinchGestureTouchZoomIn) {
CreateControllerAndTarget<MockSyntheticTouchpadPinchTouchTarget>();
SyntheticPinchGestureParams params;
params.gesture_source_type = SyntheticGestureParams::MOUSE_INPUT;
params.scale_factor = 2.3f;
params.anchor.SetPoint(54, 89);
scoped_ptr<SyntheticTouchpadPinchGesture> gesture(
new SyntheticTouchpadPinchGesture(params));
QueueSyntheticGesture(gesture.Pass());
FlushInputUntilComplete();
MockSyntheticTouchpadPinchTouchTarget* pinch_target =
static_cast<MockSyntheticTouchpadPinchTouchTarget*>(target_);
EXPECT_EQ(1, num_success_);
EXPECT_EQ(0, num_failure_);
EXPECT_EQ(pinch_target->zoom_direction(),
MockSyntheticTouchpadPinchTouchTarget::ZOOM_IN);
EXPECT_FLOAT_EQ(params.scale_factor, pinch_target->scale_factor());
}
TEST_F(SyntheticGestureControllerTest, TouchpadPinchGestureTouchZoomOut) {
CreateControllerAndTarget<MockSyntheticTouchpadPinchTouchTarget>();
SyntheticPinchGestureParams params;
params.gesture_source_type = SyntheticGestureParams::MOUSE_INPUT;
params.scale_factor = 0.4f;
params.anchor.SetPoint(-12, 93);
scoped_ptr<SyntheticTouchpadPinchGesture> gesture(
new SyntheticTouchpadPinchGesture(params));
QueueSyntheticGesture(gesture.Pass());
FlushInputUntilComplete();
MockSyntheticTouchpadPinchTouchTarget* pinch_target =
static_cast<MockSyntheticTouchpadPinchTouchTarget*>(target_);
EXPECT_EQ(1, num_success_);
EXPECT_EQ(0, num_failure_);
EXPECT_EQ(pinch_target->zoom_direction(),
MockSyntheticTouchpadPinchTouchTarget::ZOOM_OUT);
EXPECT_FLOAT_EQ(params.scale_factor, pinch_target->scale_factor());
}
TEST_F(SyntheticGestureControllerTest, TouchpadPinchGestureTouchNoScaling) {
CreateControllerAndTarget<MockSyntheticTouchpadPinchTouchTarget>();
SyntheticPinchGestureParams params;
params.gesture_source_type = SyntheticGestureParams::MOUSE_INPUT;
params.scale_factor = 1.0f;
scoped_ptr<SyntheticTouchpadPinchGesture> gesture(
new SyntheticTouchpadPinchGesture(params));
QueueSyntheticGesture(gesture.Pass());
FlushInputUntilComplete();
MockSyntheticTouchpadPinchTouchTarget* pinch_target =
static_cast<MockSyntheticTouchpadPinchTouchTarget*>(target_);
EXPECT_EQ(1, num_success_);
EXPECT_EQ(0, num_failure_);
EXPECT_EQ(pinch_target->zoom_direction(),
MockSyntheticTouchpadPinchTouchTarget::ZOOM_DIRECTION_UNKNOWN);
EXPECT_EQ(params.scale_factor, pinch_target->scale_factor());
}
// Ensure that if SyntheticPinchGesture is instantiated with TOUCH_INPUT it
// correctly creates a touchscreen gesture.
TEST_F(SyntheticGestureControllerTest, PinchGestureExplicitTouch) {
CreateControllerAndTarget<MockSyntheticTouchscreenPinchTouchTarget>();
SyntheticPinchGestureParams params;
params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;
@ -1112,54 +1316,62 @@ TEST_F(SyntheticGestureControllerTest, PinchGestureTouchZoomIn) {
QueueSyntheticGesture(gesture.Pass());
FlushInputUntilComplete();
MockSyntheticPinchTouchTarget* pinch_target =
static_cast<MockSyntheticPinchTouchTarget*>(target_);
EXPECT_EQ(1, num_success_);
EXPECT_EQ(0, num_failure_);
EXPECT_EQ(pinch_target->zoom_direction(),
MockSyntheticPinchTouchTarget::ZOOM_IN);
EXPECT_FLOAT_EQ(params.scale_factor, pinch_target->ComputeScaleFactor());
// Gesture target will fail expectations if the wrong underlying
// SyntheticPinch*Gesture was instantiated.
}
TEST_F(SyntheticGestureControllerTest, PinchGestureTouchZoomOut) {
CreateControllerAndTarget<MockSyntheticPinchTouchTarget>();
// Ensure that if SyntheticPinchGesture is instantiated with MOUSE_INPUT it
// correctly creates a touchpad gesture.
TEST_F(SyntheticGestureControllerTest, PinchGestureExplicitMouse) {
CreateControllerAndTarget<MockSyntheticTouchpadPinchTouchTarget>();
SyntheticPinchGestureParams params;
params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;
params.scale_factor = 0.4f;
params.anchor.SetPoint(-12, 93);
params.gesture_source_type = SyntheticGestureParams::MOUSE_INPUT;
params.scale_factor = 2.3f;
params.anchor.SetPoint(54, 89);
scoped_ptr<SyntheticPinchGesture> gesture(new SyntheticPinchGesture(params));
QueueSyntheticGesture(gesture.Pass());
FlushInputUntilComplete();
MockSyntheticPinchTouchTarget* pinch_target =
static_cast<MockSyntheticPinchTouchTarget*>(target_);
EXPECT_EQ(1, num_success_);
EXPECT_EQ(0, num_failure_);
EXPECT_EQ(pinch_target->zoom_direction(),
MockSyntheticPinchTouchTarget::ZOOM_OUT);
EXPECT_FLOAT_EQ(params.scale_factor, pinch_target->ComputeScaleFactor());
// Gesture target will fail expectations if the wrong underlying
// SyntheticPinch*Gesture was instantiated.
}
TEST_F(SyntheticGestureControllerTest, PinchGestureTouchNoScaling) {
CreateControllerAndTarget<MockSyntheticPinchTouchTarget>();
// Ensure that if SyntheticPinchGesture is instantiated with DEFAULT_INPUT it
// correctly creates a touchscreen gesture for a touchscreen controller.
TEST_F(SyntheticGestureControllerTest, PinchGestureDefaultTouch) {
CreateControllerAndTarget<MockSyntheticTouchscreenPinchTouchTarget>();
SyntheticPinchGestureParams params;
params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;
params.scale_factor = 1.0f;
params.gesture_source_type = SyntheticGestureParams::DEFAULT_INPUT;
params.scale_factor = 2.3f;
params.anchor.SetPoint(54, 89);
scoped_ptr<SyntheticPinchGesture> gesture(new SyntheticPinchGesture(params));
QueueSyntheticGesture(gesture.Pass());
FlushInputUntilComplete();
MockSyntheticPinchTouchTarget* pinch_target =
static_cast<MockSyntheticPinchTouchTarget*>(target_);
EXPECT_EQ(1, num_success_);
EXPECT_EQ(0, num_failure_);
EXPECT_EQ(pinch_target->zoom_direction(),
MockSyntheticPinchTouchTarget::ZOOM_DIRECTION_UNKNOWN);
EXPECT_EQ(params.scale_factor, pinch_target->ComputeScaleFactor());
// Gesture target will fail expectations if the wrong underlying
// SyntheticPinch*Gesture was instantiated.
}
// Ensure that if SyntheticPinchGesture is instantiated with DEFAULT_INPUT it
// correctly creates a touchpad gesture for a touchpad controller.
TEST_F(SyntheticGestureControllerTest, PinchGestureDefaultMouse) {
CreateControllerAndTarget<MockSyntheticTouchpadPinchTouchTarget>();
SyntheticPinchGestureParams params;
params.gesture_source_type = SyntheticGestureParams::DEFAULT_INPUT;
params.scale_factor = 2.3f;
params.anchor.SetPoint(54, 89);
scoped_ptr<SyntheticPinchGesture> gesture(new SyntheticPinchGesture(params));
QueueSyntheticGesture(gesture.Pass());
FlushInputUntilComplete();
// Gesture target will fail expectations if the wrong underlying
// SyntheticPinch*Gesture was instantiated.
}
TEST_F(SyntheticGestureControllerTest, TapGestureTouch) {

@ -0,0 +1,31 @@
// Copyright 2015 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 CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_GESTURE_TARGET_MAC_H_
#define CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_GESTURE_TARGET_MAC_H_
#include "content/browser/renderer_host/input/synthetic_gesture_target_base.h"
#include "content/browser/renderer_host/render_widget_host_view_mac.h"
#include "content/common/input/synthetic_gesture_params.h"
namespace content {
// SyntheticGestureTarget implementation for mac
class SyntheticGestureTargetMac : public SyntheticGestureTargetBase {
public:
SyntheticGestureTargetMac(RenderWidgetHostImpl* host,
RenderWidgetHostViewCocoa* cocoa_view);
// SyntheticGestureTarget:
void DispatchInputEventToPlatform(const blink::WebInputEvent& event) override;
private:
RenderWidgetHostViewCocoa* cocoa_view_;
DISALLOW_COPY_AND_ASSIGN(SyntheticGestureTargetMac);
};
} // namespace content
#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_GESTURE_TARGET_MAC_H_

@ -0,0 +1,122 @@
// Copyright 2015 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 "content/browser/renderer_host/input/synthetic_gesture_target_mac.h"
#include "base/mac/scoped_nsautorelease_pool.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
// Unlike some event APIs, Apple does not provide a way to programmatically
// build a zoom event. To work around this, we leverage ObjectiveC's flexible
// typing and build up an object with the right interface to provide a zoom
// event.
@interface SyntheticPinchEvent : NSObject
// Populated based on desired zoom level.
@property CGFloat magnification;
@property NSPoint locationInWindow;
@property NSEventType type;
// Filled with default values.
@property(readonly) CGFloat deltaX;
@property(readonly) CGFloat deltaY;
@property(readonly) NSEventModifierFlags modifierFlags;
@property(readonly) NSTimeInterval timestamp;
@end
@implementation SyntheticPinchEvent
@synthesize magnification = magnification_;
@synthesize locationInWindow = locationInWindow_;
@synthesize type = type_;
@synthesize deltaX = deltaX_;
@synthesize deltaY = deltaY_;
@synthesize modifierFlags = modifierFlags_;
@synthesize timestamp = timestamp_;
- (id)initWithMagnification:(float)magnification
locationInWindow:(NSPoint)location {
self = [super init];
if (self) {
type_ = NSEventTypeMagnify;
magnification_ = magnification;
locationInWindow_ = location;
deltaX_ = 0;
deltaY_ = 0;
modifierFlags_ = 0;
// Default timestamp to current time.
timestamp_ = [[NSDate date] timeIntervalSince1970];
}
return self;
}
+ (id)eventWithMagnification:(float)magnification
locationInWindow:(NSPoint)location {
SyntheticPinchEvent* event =
[[SyntheticPinchEvent alloc] initWithMagnification:magnification
locationInWindow:location];
return [event autorelease];
}
@end
using blink::WebInputEvent;
using blink::WebGestureEvent;
namespace content {
SyntheticGestureTargetMac::SyntheticGestureTargetMac(
RenderWidgetHostImpl* host,
RenderWidgetHostViewCocoa* cocoa_view)
: SyntheticGestureTargetBase(host), cocoa_view_(cocoa_view) {}
void SyntheticGestureTargetMac::DispatchInputEventToPlatform(
const WebInputEvent& event) {
if (WebInputEvent::isGestureEventType(event.type)) {
// Create an autorelease pool so that we clean up any synthetic events we
// generate.
base::mac::ScopedNSAutoreleasePool pool;
const WebGestureEvent* gesture_event =
static_cast<const WebGestureEvent*>(&event);
switch (event.type) {
case WebInputEvent::GesturePinchBegin: {
id event = [SyntheticPinchEvent
eventWithMagnification:0.0f
locationInWindow:NSMakePoint(gesture_event->x,
gesture_event->y)];
[cocoa_view_ beginGestureWithEvent:event];
return;
}
case WebInputEvent::GesturePinchEnd: {
id event = [SyntheticPinchEvent
eventWithMagnification:0.0f
locationInWindow:NSMakePoint(gesture_event->x,
gesture_event->y)];
[cocoa_view_ endGestureWithEvent:event];
return;
}
case WebInputEvent::GesturePinchUpdate: {
id event = [SyntheticPinchEvent
eventWithMagnification:gesture_event->data.pinchUpdate.scale - 1.0f
locationInWindow:NSMakePoint(gesture_event->x,
gesture_event->y)];
[cocoa_view_ magnifyWithEvent:event];
return;
}
default:
break;
}
}
// This event wasn't handled yet, forward to the base class.
SyntheticGestureTargetBase::DispatchInputEventToPlatform(event);
}
} // namespace content

@ -1,165 +1,39 @@
// Copyright 2013 The Chromium Authors. All rights reserved.
// Copyright 2015 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 "content/browser/renderer_host/input/synthetic_pinch_gesture.h"
#include <cmath>
#include "base/logging.h"
#include "ui/events/latency_info.h"
#include "content/browser/renderer_host/input/synthetic_touchpad_pinch_gesture.h"
#include "content/browser/renderer_host/input/synthetic_touchscreen_pinch_gesture.h"
namespace content {
SyntheticPinchGesture::SyntheticPinchGesture(
const SyntheticPinchGestureParams& params)
: params_(params),
start_y_0_(0.0f),
start_y_1_(0.0f),
max_pointer_delta_0_(0.0f),
gesture_source_type_(SyntheticGestureParams::DEFAULT_INPUT),
state_(SETUP) {
DCHECK_GT(params_.scale_factor, 0.0f);
}
: params_(params) {}
SyntheticPinchGesture::~SyntheticPinchGesture() {}
SyntheticGesture::Result SyntheticPinchGesture::ForwardInputEvents(
const base::TimeTicks& timestamp, SyntheticGestureTarget* target) {
if (state_ == SETUP) {
gesture_source_type_ = params_.gesture_source_type;
if (gesture_source_type_ == SyntheticGestureParams::DEFAULT_INPUT)
gesture_source_type_ = target->GetDefaultSyntheticGestureSourceType();
state_ = STARTED;
start_time_ = timestamp;
}
DCHECK_NE(gesture_source_type_, SyntheticGestureParams::DEFAULT_INPUT);
if (gesture_source_type_ == SyntheticGestureParams::TOUCH_INPUT)
ForwardTouchInputEvents(timestamp, target);
else
return SyntheticGesture::GESTURE_SOURCE_TYPE_NOT_IMPLEMENTED;
return (state_ == DONE) ? SyntheticGesture::GESTURE_FINISHED
: SyntheticGesture::GESTURE_RUNNING;
}
void SyntheticPinchGesture::ForwardTouchInputEvents(
const base::TimeTicks& timestamp, SyntheticGestureTarget* target) {
switch (state_) {
case STARTED:
// Check for an early finish.
if (params_.scale_factor == 1.0f) {
state_ = DONE;
break;
}
SetupCoordinatesAndStopTime(target);
PressTouchPoints(target, timestamp);
state_ = MOVING;
break;
case MOVING: {
base::TimeTicks event_timestamp = ClampTimestamp(timestamp);
float delta = GetDeltaForPointer0AtTime(event_timestamp);
MoveTouchPoints(target, delta, event_timestamp);
if (HasReachedTarget(event_timestamp)) {
ReleaseTouchPoints(target, event_timestamp);
state_ = DONE;
}
} break;
case SETUP:
NOTREACHED() << "State SETUP invalid for synthetic pinch.";
case DONE:
NOTREACHED() << "State DONE invalid for synthetic pinch.";
}
}
void SyntheticPinchGesture::PressTouchPoints(SyntheticGestureTarget* target,
const base::TimeTicks& timestamp) {
touch_event_.PressPoint(params_.anchor.x(), start_y_0_);
touch_event_.PressPoint(params_.anchor.x(), start_y_1_);
ForwardTouchEvent(target, timestamp);
}
void SyntheticPinchGesture::MoveTouchPoints(SyntheticGestureTarget* target,
float delta,
const base::TimeTicks& timestamp) {
// The two pointers move in opposite directions.
float current_y_0 = start_y_0_ + delta;
float current_y_1 = start_y_1_ - delta;
touch_event_.MovePoint(0, params_.anchor.x(), current_y_0);
touch_event_.MovePoint(1, params_.anchor.x(), current_y_1);
ForwardTouchEvent(target, timestamp);
}
void SyntheticPinchGesture::ReleaseTouchPoints(
SyntheticGestureTarget* target, const base::TimeTicks& timestamp) {
touch_event_.ReleasePoint(0);
touch_event_.ReleasePoint(1);
ForwardTouchEvent(target, timestamp);
}
void SyntheticPinchGesture::ForwardTouchEvent(
SyntheticGestureTarget* target, const base::TimeTicks& timestamp) {
touch_event_.timeStampSeconds = ConvertTimestampToSeconds(timestamp);
target->DispatchInputEventToPlatform(touch_event_);
}
void SyntheticPinchGesture::SetupCoordinatesAndStopTime(
const base::TimeTicks& timestamp,
SyntheticGestureTarget* target) {
// To achieve the specified scaling factor, the ratio of the final to the
// initial span (distance between the pointers) has to be equal to the scaling
// factor. Since we're moving both pointers at the same speed, each pointer's
// distance to the anchor is half the span.
float initial_distance_to_anchor, final_distance_to_anchor;
if (params_.scale_factor > 1.0f) { // zooming in
initial_distance_to_anchor = target->GetMinScalingSpanInDips() / 2.0f;
final_distance_to_anchor =
(initial_distance_to_anchor + target->GetTouchSlopInDips()) *
params_.scale_factor;
} else { // zooming out
final_distance_to_anchor = target->GetMinScalingSpanInDips() / 2.0f;
initial_distance_to_anchor =
(final_distance_to_anchor / params_.scale_factor) +
target->GetTouchSlopInDips();
if (!lazy_gesture_) {
SyntheticGestureParams::GestureSourceType source_type =
params_.gesture_source_type;
if (source_type == SyntheticGestureParams::DEFAULT_INPUT) {
source_type = target->GetDefaultSyntheticGestureSourceType();
}
DCHECK_NE(SyntheticGestureParams::DEFAULT_INPUT, source_type);
if (source_type == SyntheticGestureParams::TOUCH_INPUT) {
lazy_gesture_.reset(new SyntheticTouchscreenPinchGesture(params_));
} else {
DCHECK_EQ(SyntheticGestureParams::MOUSE_INPUT, source_type);
lazy_gesture_.reset(new SyntheticTouchpadPinchGesture(params_));
}
}
start_y_0_ = params_.anchor.y() - initial_distance_to_anchor;
start_y_1_ = params_.anchor.y() + initial_distance_to_anchor;
max_pointer_delta_0_ = initial_distance_to_anchor - final_distance_to_anchor;
int64 total_duration_in_us = static_cast<int64>(
1e6 * (static_cast<double>(std::abs(2 * max_pointer_delta_0_)) /
params_.relative_pointer_speed_in_pixels_s));
DCHECK_GT(total_duration_in_us, 0);
stop_time_ =
start_time_ + base::TimeDelta::FromMicroseconds(total_duration_in_us);
}
float SyntheticPinchGesture::GetDeltaForPointer0AtTime(
const base::TimeTicks& timestamp) const {
// Make sure the final delta is correct. Using the computation below can lead
// to issues with floating point precision.
if (HasReachedTarget(timestamp))
return max_pointer_delta_0_;
float total_abs_delta = params_.relative_pointer_speed_in_pixels_s *
(timestamp - start_time_).InSecondsF();
float abs_delta_pointer_0 = total_abs_delta / 2.0f;
return (params_.scale_factor > 1.0f) ? -abs_delta_pointer_0
: abs_delta_pointer_0;
}
base::TimeTicks SyntheticPinchGesture::ClampTimestamp(
const base::TimeTicks& timestamp) const {
return std::min(timestamp, stop_time_);
}
bool SyntheticPinchGesture::HasReachedTarget(const base::TimeTicks& timestamp)
const {
return timestamp >= stop_time_;
return lazy_gesture_->ForwardInputEvents(timestamp, target);
}
} // namespace content

@ -1,4 +1,4 @@
// Copyright 2013 The Chromium Authors. All rights reserved.
// Copyright 2015 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.
@ -10,11 +10,13 @@
#include "content/browser/renderer_host/input/synthetic_gesture_target.h"
#include "content/common/content_export.h"
#include "content/common/input/synthetic_pinch_gesture_params.h"
#include "content/common/input/synthetic_web_input_event_builders.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
namespace content {
// SyntheticPinchGesture is a thin wrapper around either
// SyntheticTouchscreenPinchGesture or SyntheticTouchpadPinchGesture, depending
// on the SyntheticGestureParam's |input_type| and the default input type of the
// target.
class CONTENT_EXPORT SyntheticPinchGesture : public SyntheticGesture {
public:
explicit SyntheticPinchGesture(const SyntheticPinchGestureParams& params);
@ -25,42 +27,9 @@ class CONTENT_EXPORT SyntheticPinchGesture : public SyntheticGesture {
SyntheticGestureTarget* target) override;
private:
enum GestureState {
SETUP,
STARTED,
MOVING,
DONE
};
void ForwardTouchInputEvents(const base::TimeTicks& timestamp,
SyntheticGestureTarget* target);
void UpdateTouchPoints(const base::TimeTicks& timestamp);
void PressTouchPoints(SyntheticGestureTarget* target,
const base::TimeTicks& timestamp);
void MoveTouchPoints(SyntheticGestureTarget* target, float delta,
const base::TimeTicks& timestamp);
void ReleaseTouchPoints(SyntheticGestureTarget* target,
const base::TimeTicks& timestamp);
void ForwardTouchEvent(SyntheticGestureTarget* target,
const base::TimeTicks& timestamp);
void SetupCoordinatesAndStopTime(SyntheticGestureTarget* target);
float GetDeltaForPointer0AtTime(const base::TimeTicks& timestamp) const;
base::TimeTicks ClampTimestamp(const base::TimeTicks& timestamp) const;
bool HasReachedTarget(const base::TimeTicks& timestamp) const;
SyntheticPinchGestureParams params_;
float start_y_0_;
float start_y_1_;
float max_pointer_delta_0_;
SyntheticGestureParams::GestureSourceType gesture_source_type_;
GestureState state_;
SyntheticWebTouchEvent touch_event_;
base::TimeTicks start_time_;
base::TimeTicks stop_time_;
scoped_ptr<SyntheticGesture> lazy_gesture_;
private:
DISALLOW_COPY_AND_ASSIGN(SyntheticPinchGesture);
};

@ -0,0 +1,150 @@
// Copyright 2015 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 "content/browser/renderer_host/input/synthetic_touchpad_pinch_gesture.h"
namespace content {
namespace {
float Lerp(float start, float end, float progress) {
return start + progress * (end - start);
}
} // namespace
SyntheticTouchpadPinchGesture::SyntheticTouchpadPinchGesture(
const SyntheticPinchGestureParams& params)
: params_(params),
gesture_source_type_(SyntheticGestureParams::DEFAULT_INPUT),
state_(SETUP),
current_scale_(1.0f) {
DCHECK_GT(params_.scale_factor, 0.0f);
}
SyntheticTouchpadPinchGesture::~SyntheticTouchpadPinchGesture() {}
SyntheticGesture::Result SyntheticTouchpadPinchGesture::ForwardInputEvents(
const base::TimeTicks& timestamp,
SyntheticGestureTarget* target) {
if (state_ == SETUP) {
gesture_source_type_ = params_.gesture_source_type;
if (gesture_source_type_ == SyntheticGestureParams::DEFAULT_INPUT)
gesture_source_type_ = target->GetDefaultSyntheticGestureSourceType();
state_ = STARTED;
start_time_ = timestamp;
}
DCHECK_NE(gesture_source_type_, SyntheticGestureParams::DEFAULT_INPUT);
if (gesture_source_type_ == SyntheticGestureParams::MOUSE_INPUT) {
ForwardGestureEvents(timestamp, target);
} else {
// Touch input should be using SyntheticTouchscreenPinchGesture.
return SyntheticGesture::GESTURE_SOURCE_TYPE_NOT_IMPLEMENTED;
}
return (state_ == DONE) ? SyntheticGesture::GESTURE_FINISHED
: SyntheticGesture::GESTURE_RUNNING;
}
void SyntheticTouchpadPinchGesture::ForwardGestureEvents(
const base::TimeTicks& timestamp,
SyntheticGestureTarget* target) {
switch (state_) {
case STARTED:
// Check for an early finish.
if (params_.scale_factor == 1.0f) {
state_ = DONE;
break;
}
CalculateEndTime(target);
// Send the start event.
target->DispatchInputEventToPlatform(
SyntheticWebGestureEventBuilder::Build(
blink::WebGestureEvent::GesturePinchBegin,
blink::WebGestureDeviceTouchpad));
state_ = IN_PROGRESS;
break;
case IN_PROGRESS: {
base::TimeTicks event_timestamp = ClampTimestamp(timestamp);
float target_scale = CalculateTargetScale(event_timestamp);
float incremental_scale = target_scale / current_scale_;
current_scale_ = target_scale;
// Send the incremental scale event.
target->DispatchInputEventToPlatform(
SyntheticWebGestureEventBuilder::BuildPinchUpdate(
incremental_scale, params_.anchor.x(), params_.anchor.y(),
0 /* modifierFlags */, blink::WebGestureDeviceTouchpad));
if (HasReachedTarget(event_timestamp)) {
target->DispatchInputEventToPlatform(
SyntheticWebGestureEventBuilder::Build(
blink::WebGestureEvent::GesturePinchEnd,
blink::WebGestureDeviceTouchpad));
state_ = DONE;
}
break;
}
case SETUP:
NOTREACHED() << "State SETUP invalid for synthetic pinch.";
case DONE:
NOTREACHED() << "State DONE invalid for synthetic pinch.";
}
}
float SyntheticTouchpadPinchGesture::CalculateTargetScale(
const base::TimeTicks& timestamp) const {
// Make sure the final delta is correct. Using the computation below can lead
// to issues with floating point precision.
if (HasReachedTarget(timestamp))
return params_.scale_factor;
float progress = (timestamp - start_time_).InSecondsF() /
(stop_time_ - start_time_).InSecondsF();
return Lerp(1.0f, params_.scale_factor, progress);
}
// Calculate an end time based on the amount of scaling to be done and the
// |relative_pointer_speed_in_pixels_s|. Because we don't have an actual pixel
// delta, we assume that a pinch of 200 pixels is needed to double the screen
// size and generate a stop time based on that.
// TODO(ericrk): We should not calculate duration from
// |relative_pointer_speed_in_pixels_s|, but should instead get a duration from
// a SyntheticTouchpadPinchGestureParams type. crbug.com/534976
void SyntheticTouchpadPinchGesture::CalculateEndTime(
SyntheticGestureTarget* target) {
const int kPixelsNeededToDoubleOrHalve = 200;
float scale_factor = params_.scale_factor;
if (scale_factor < 1.0f) {
// If we are scaling down, calculate the time based on the inverse so that
// halving or doubling the scale takes the same amount of time.
scale_factor = 1.0f / scale_factor;
}
float scale_factor_delta =
(scale_factor - 1.0f) * kPixelsNeededToDoubleOrHalve;
int64 total_duration_in_us =
static_cast<int64>(1e6 * (static_cast<double>(scale_factor_delta) /
params_.relative_pointer_speed_in_pixels_s));
DCHECK_GT(total_duration_in_us, 0);
stop_time_ =
start_time_ + base::TimeDelta::FromMicroseconds(total_duration_in_us);
}
base::TimeTicks SyntheticTouchpadPinchGesture::ClampTimestamp(
const base::TimeTicks& timestamp) const {
return std::min(timestamp, stop_time_);
}
bool SyntheticTouchpadPinchGesture::HasReachedTarget(
const base::TimeTicks& timestamp) const {
return timestamp >= stop_time_;
}
} // namespace content

@ -0,0 +1,54 @@
// Copyright 2015 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 CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_TOUCHPAD_PINCH_GESTURE_H_
#define CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_TOUCHPAD_PINCH_GESTURE_H_
#include "base/time/time.h"
#include "content/browser/renderer_host/input/synthetic_gesture.h"
#include "content/browser/renderer_host/input/synthetic_gesture_target.h"
#include "content/common/content_export.h"
#include "content/common/input/synthetic_pinch_gesture_params.h"
#include "content/common/input/synthetic_web_input_event_builders.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
namespace content {
class CONTENT_EXPORT SyntheticTouchpadPinchGesture : public SyntheticGesture {
public:
explicit SyntheticTouchpadPinchGesture(
const SyntheticPinchGestureParams& params);
~SyntheticTouchpadPinchGesture() override;
SyntheticGesture::Result ForwardInputEvents(
const base::TimeTicks& timestamp,
SyntheticGestureTarget* target) override;
private:
enum GestureState { SETUP, STARTED, IN_PROGRESS, DONE };
void ForwardGestureEvents(const base::TimeTicks& timestamp,
SyntheticGestureTarget* target);
void UpdateTouchPoints(const base::TimeTicks& timestamp);
void CalculateEndTime(SyntheticGestureTarget* target);
float CalculateTargetScale(const base::TimeTicks& timestamp) const;
base::TimeTicks ClampTimestamp(const base::TimeTicks& timestamp) const;
bool HasReachedTarget(const base::TimeTicks& timestamp) const;
SyntheticPinchGestureParams params_;
SyntheticGestureParams::GestureSourceType gesture_source_type_;
GestureState state_;
base::TimeTicks start_time_;
base::TimeTicks stop_time_;
float current_scale_;
private:
DISALLOW_COPY_AND_ASSIGN(SyntheticTouchpadPinchGesture);
};
} // namespace content
#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_TOUCHPAD_PINCH_GESTURE_H_

@ -0,0 +1,172 @@
// Copyright 2013 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 "content/browser/renderer_host/input/synthetic_touchscreen_pinch_gesture.h"
#include <cmath>
#include "base/logging.h"
#include "ui/events/latency_info.h"
namespace content {
SyntheticTouchscreenPinchGesture::SyntheticTouchscreenPinchGesture(
const SyntheticPinchGestureParams& params)
: params_(params),
start_y_0_(0.0f),
start_y_1_(0.0f),
max_pointer_delta_0_(0.0f),
gesture_source_type_(SyntheticGestureParams::DEFAULT_INPUT),
state_(SETUP) {
DCHECK_GT(params_.scale_factor, 0.0f);
}
SyntheticTouchscreenPinchGesture::~SyntheticTouchscreenPinchGesture() {}
SyntheticGesture::Result SyntheticTouchscreenPinchGesture::ForwardInputEvents(
const base::TimeTicks& timestamp,
SyntheticGestureTarget* target) {
if (state_ == SETUP) {
gesture_source_type_ = params_.gesture_source_type;
if (gesture_source_type_ == SyntheticGestureParams::DEFAULT_INPUT)
gesture_source_type_ = target->GetDefaultSyntheticGestureSourceType();
state_ = STARTED;
start_time_ = timestamp;
}
DCHECK_NE(gesture_source_type_, SyntheticGestureParams::DEFAULT_INPUT);
if (gesture_source_type_ == SyntheticGestureParams::TOUCH_INPUT) {
ForwardTouchInputEvents(timestamp, target);
} else {
return SyntheticGesture::GESTURE_SOURCE_TYPE_NOT_IMPLEMENTED;
}
return (state_ == DONE) ? SyntheticGesture::GESTURE_FINISHED
: SyntheticGesture::GESTURE_RUNNING;
}
void SyntheticTouchscreenPinchGesture::ForwardTouchInputEvents(
const base::TimeTicks& timestamp,
SyntheticGestureTarget* target) {
switch (state_) {
case STARTED:
// Check for an early finish.
if (params_.scale_factor == 1.0f) {
state_ = DONE;
break;
}
SetupCoordinatesAndStopTime(target);
PressTouchPoints(target, timestamp);
state_ = MOVING;
break;
case MOVING: {
base::TimeTicks event_timestamp = ClampTimestamp(timestamp);
float delta = GetDeltaForPointer0AtTime(event_timestamp);
MoveTouchPoints(target, delta, event_timestamp);
if (HasReachedTarget(event_timestamp)) {
ReleaseTouchPoints(target, event_timestamp);
state_ = DONE;
}
} break;
case SETUP:
NOTREACHED() << "State SETUP invalid for synthetic pinch.";
case DONE:
NOTREACHED() << "State DONE invalid for synthetic pinch.";
}
}
void SyntheticTouchscreenPinchGesture::PressTouchPoints(
SyntheticGestureTarget* target,
const base::TimeTicks& timestamp) {
touch_event_.PressPoint(params_.anchor.x(), start_y_0_);
touch_event_.PressPoint(params_.anchor.x(), start_y_1_);
ForwardTouchEvent(target, timestamp);
}
void SyntheticTouchscreenPinchGesture::MoveTouchPoints(
SyntheticGestureTarget* target,
float delta,
const base::TimeTicks& timestamp) {
// The two pointers move in opposite directions.
float current_y_0 = start_y_0_ + delta;
float current_y_1 = start_y_1_ - delta;
touch_event_.MovePoint(0, params_.anchor.x(), current_y_0);
touch_event_.MovePoint(1, params_.anchor.x(), current_y_1);
ForwardTouchEvent(target, timestamp);
}
void SyntheticTouchscreenPinchGesture::ReleaseTouchPoints(
SyntheticGestureTarget* target,
const base::TimeTicks& timestamp) {
touch_event_.ReleasePoint(0);
touch_event_.ReleasePoint(1);
ForwardTouchEvent(target, timestamp);
}
void SyntheticTouchscreenPinchGesture::ForwardTouchEvent(
SyntheticGestureTarget* target,
const base::TimeTicks& timestamp) {
touch_event_.timeStampSeconds = ConvertTimestampToSeconds(timestamp);
target->DispatchInputEventToPlatform(touch_event_);
}
void SyntheticTouchscreenPinchGesture::SetupCoordinatesAndStopTime(
SyntheticGestureTarget* target) {
// To achieve the specified scaling factor, the ratio of the final to the
// initial span (distance between the pointers) has to be equal to the scaling
// factor. Since we're moving both pointers at the same speed, each pointer's
// distance to the anchor is half the span.
float initial_distance_to_anchor, final_distance_to_anchor;
if (params_.scale_factor > 1.0f) { // zooming in
initial_distance_to_anchor = target->GetMinScalingSpanInDips() / 2.0f;
final_distance_to_anchor =
(initial_distance_to_anchor + target->GetTouchSlopInDips()) *
params_.scale_factor;
} else { // zooming out
final_distance_to_anchor = target->GetMinScalingSpanInDips() / 2.0f;
initial_distance_to_anchor =
(final_distance_to_anchor / params_.scale_factor) +
target->GetTouchSlopInDips();
}
start_y_0_ = params_.anchor.y() - initial_distance_to_anchor;
start_y_1_ = params_.anchor.y() + initial_distance_to_anchor;
max_pointer_delta_0_ = initial_distance_to_anchor - final_distance_to_anchor;
int64 total_duration_in_us = static_cast<int64>(
1e6 * (static_cast<double>(std::abs(2 * max_pointer_delta_0_)) /
params_.relative_pointer_speed_in_pixels_s));
DCHECK_GT(total_duration_in_us, 0);
stop_time_ =
start_time_ + base::TimeDelta::FromMicroseconds(total_duration_in_us);
}
float SyntheticTouchscreenPinchGesture::GetDeltaForPointer0AtTime(
const base::TimeTicks& timestamp) const {
// Make sure the final delta is correct. Using the computation below can lead
// to issues with floating point precision.
if (HasReachedTarget(timestamp))
return max_pointer_delta_0_;
float total_abs_delta = params_.relative_pointer_speed_in_pixels_s *
(timestamp - start_time_).InSecondsF();
float abs_delta_pointer_0 = total_abs_delta / 2.0f;
return (params_.scale_factor > 1.0f) ? -abs_delta_pointer_0
: abs_delta_pointer_0;
}
base::TimeTicks SyntheticTouchscreenPinchGesture::ClampTimestamp(
const base::TimeTicks& timestamp) const {
return std::min(timestamp, stop_time_);
}
bool SyntheticTouchscreenPinchGesture::HasReachedTarget(
const base::TimeTicks& timestamp) const {
return timestamp >= stop_time_;
}
} // namespace content

@ -0,0 +1,67 @@
// Copyright 2013 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 CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_TOUCHSCREEN_PINCH_GESTURE_H_
#define CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_TOUCHSCREEN_PINCH_GESTURE_H_
#include "base/time/time.h"
#include "content/browser/renderer_host/input/synthetic_gesture.h"
#include "content/browser/renderer_host/input/synthetic_gesture_target.h"
#include "content/common/content_export.h"
#include "content/common/input/synthetic_pinch_gesture_params.h"
#include "content/common/input/synthetic_web_input_event_builders.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
namespace content {
class CONTENT_EXPORT SyntheticTouchscreenPinchGesture
: public SyntheticGesture {
public:
explicit SyntheticTouchscreenPinchGesture(
const SyntheticPinchGestureParams& params);
~SyntheticTouchscreenPinchGesture() override;
SyntheticGesture::Result ForwardInputEvents(
const base::TimeTicks& timestamp,
SyntheticGestureTarget* target) override;
private:
enum GestureState { SETUP, STARTED, MOVING, DONE };
void ForwardTouchInputEvents(const base::TimeTicks& timestamp,
SyntheticGestureTarget* target);
void UpdateTouchPoints(const base::TimeTicks& timestamp);
void PressTouchPoints(SyntheticGestureTarget* target,
const base::TimeTicks& timestamp);
void MoveTouchPoints(SyntheticGestureTarget* target,
float delta,
const base::TimeTicks& timestamp);
void ReleaseTouchPoints(SyntheticGestureTarget* target,
const base::TimeTicks& timestamp);
void ForwardTouchEvent(SyntheticGestureTarget* target,
const base::TimeTicks& timestamp);
void SetupCoordinatesAndStopTime(SyntheticGestureTarget* target);
float GetDeltaForPointer0AtTime(const base::TimeTicks& timestamp) const;
base::TimeTicks ClampTimestamp(const base::TimeTicks& timestamp) const;
bool HasReachedTarget(const base::TimeTicks& timestamp) const;
SyntheticPinchGestureParams params_;
float start_y_0_;
float start_y_1_;
float max_pointer_delta_0_;
SyntheticGestureParams::GestureSourceType gesture_source_type_;
GestureState state_;
SyntheticWebTouchEvent touch_event_;
base::TimeTicks start_time_;
base::TimeTicks stop_time_;
private:
DISALLOW_COPY_AND_ASSIGN(SyntheticTouchscreenPinchGesture);
};
} // namespace content
#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_TOUCHSCREEN_PINCH_GESTURE_H_

@ -342,6 +342,8 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
void WheelEventAck(const blink::WebMouseWheelEvent& event,
InputEventAckState ack_result) override;
scoped_ptr<SyntheticGestureTarget> CreateSyntheticGestureTarget() override;
uint32_t GetSurfaceIdNamespace() override;
uint32_t SurfaceIdNamespaceAtPoint(const gfx::Point& point,
gfx::Point* transformed_point) override;

@ -42,6 +42,7 @@
#include "content/browser/renderer_host/render_widget_helper.h"
#include "content/browser/renderer_host/render_widget_host_delegate.h"
#include "content/browser/renderer_host/render_widget_host_input_event_router.h"
#import "content/browser/renderer_host/input/synthetic_gesture_target_mac.h"
#import "content/browser/renderer_host/render_widget_host_view_mac_dictionary_helper.h"
#import "content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper.h"
#include "content/browser/renderer_host/render_widget_resize_helper_mac.h"
@ -1638,6 +1639,14 @@ void RenderWidgetHostViewMac::WheelEventAck(
[cocoa_view_ processedWheelEvent:event consumed:consumed];
}
scoped_ptr<SyntheticGestureTarget>
RenderWidgetHostViewMac::CreateSyntheticGestureTarget() {
RenderWidgetHostImpl* host =
RenderWidgetHostImpl::From(GetRenderWidgetHost());
return scoped_ptr<SyntheticGestureTarget>(
new SyntheticGestureTargetMac(host, cocoa_view_));
}
uint32_t RenderWidgetHostViewMac::GetSurfaceIdNamespace() {
DCHECK(delegated_frame_host_);
return delegated_frame_host_->GetSurfaceIdNamespace();

@ -1199,8 +1199,14 @@
'browser/renderer_host/input/synthetic_gesture_target_aura.h',
'browser/renderer_host/input/synthetic_gesture_target_base.cc',
'browser/renderer_host/input/synthetic_gesture_target_base.h',
'browser/renderer_host/input/synthetic_gesture_target_mac.mm',
'browser/renderer_host/input/synthetic_gesture_target_mac.h',
'browser/renderer_host/input/synthetic_pinch_gesture.cc',
'browser/renderer_host/input/synthetic_pinch_gesture.h',
'browser/renderer_host/input/synthetic_touchpad_pinch_gesture.cc',
'browser/renderer_host/input/synthetic_touchpad_pinch_gesture.h',
'browser/renderer_host/input/synthetic_touchscreen_pinch_gesture.cc',
'browser/renderer_host/input/synthetic_touchscreen_pinch_gesture.h',
'browser/renderer_host/input/synthetic_smooth_drag_gesture.cc',
'browser/renderer_host/input/synthetic_smooth_drag_gesture.h',
'browser/renderer_host/input/synthetic_smooth_move_gesture.cc',

@ -250,7 +250,7 @@ class SmoothnessFlingSimpleMobilePages(perf_benchmark.PerfBenchmark):
return 'smoothness.fling.simple_mobile_sites'
@benchmark.Enabled('android', 'chromeos')
@benchmark.Enabled('android', 'chromeos', 'mac')
class SmoothnessToughPinchZoomCases(perf_benchmark.PerfBenchmark):
"""Measures rendering statistics for pinch-zooming into the tough pinch zoom
cases.

@ -43,15 +43,6 @@ class PinchAction(page_action.PageAction):
'This version of the browser doesn\'t support the new JS interface '
'for pinch gestures.')
if (self._synthetic_gesture_source ==
'chrome.gpuBenchmarking.MOUSE_INPUT'):
raise page_action.PageActionNotSupported(
'Pinch page action does not support mouse input')
if not page_action.IsGestureSourceTypeSupported(tab, 'touch'):
raise page_action.PageActionNotSupported(
'Touch input not supported for this browser')
done_callback = 'function() { window.__pinchActionDone = true; }'
tab.ExecuteJavaScript("""
window.__pinchActionDone = false;