Commit 6a565f0f authored by jdduke@chromium.org's avatar jdduke@chromium.org

Avoid heap allocations with GestureEventDataPacket

There are typically only a few events in a given gesture packet.  Avoid heap
allocating in the common case by switching from a raw vector to a StackVector.

BUG=395168

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@284728 0039d316-1c4b-4281-b951-d872f2087c98
parent cadece29
......@@ -277,6 +277,7 @@ test("events_unittests") {
"event_unittest.cc",
"gestures/velocity_calculator_unittest.cc",
"gesture_detection/bitset_32_unittest.cc",
"gesture_detection/gesture_event_data_packet_unittest.cc",
"gesture_detection/gesture_provider_unittest.cc",
"gesture_detection/velocity_tracker_unittest.cc",
"gesture_detection/touch_disposition_gesture_filter_unittest.cc",
......
......@@ -302,6 +302,7 @@
'gestures/motion_event_aura_unittest.cc',
'gestures/velocity_calculator_unittest.cc',
'gesture_detection/bitset_32_unittest.cc',
'gesture_detection/gesture_event_data_packet_unittest.cc',
'gesture_detection/gesture_provider_unittest.cc',
'gesture_detection/velocity_tracker_unittest.cc',
'gesture_detection/touch_disposition_gesture_filter_unittest.cc',
......
......@@ -72,7 +72,7 @@ GestureEventDataPacket& GestureEventDataPacket::operator=(
void GestureEventDataPacket::Push(const GestureEventData& gesture) {
DCHECK_NE(ET_UNKNOWN, gesture.type());
gestures_.push_back(gesture);
gestures_->push_back(gesture);
}
GestureEventDataPacket GestureEventDataPacket::FromTouch(
......
......@@ -5,8 +5,7 @@
#ifndef UI_EVENTS_GESTURE_DETECTION_GESTURE_EVENT_DATA_PACKET_H_
#define UI_EVENTS_GESTURE_DETECTION_GESTURE_EVENT_DATA_PACKET_H_
#include <vector>
#include "base/containers/stack_container.h"
#include "ui/events/gesture_detection/gesture_detection_export.h"
#include "ui/events/gesture_detection/gesture_event_data.h"
......@@ -44,7 +43,7 @@ class GESTURE_DETECTION_EXPORT GestureEventDataPacket {
const base::TimeTicks& timestamp() const { return timestamp_; }
const GestureEventData& gesture(size_t i) const { return gestures_[i]; }
size_t gesture_count() const { return gestures_.size(); }
size_t gesture_count() const { return gestures_->size(); }
GestureSource gesture_source() const { return gesture_source_; }
const gfx::PointF& touch_location() const { return touch_location_; }
const gfx::PointF& raw_touch_location() const { return raw_touch_location_; }
......@@ -55,9 +54,9 @@ class GESTURE_DETECTION_EXPORT GestureEventDataPacket {
const gfx::PointF& touch_location,
const gfx::PointF& raw_touch_location);
enum { kTypicalMaxGesturesPerTouch = 5 };
base::TimeTicks timestamp_;
// TODO(jdduke): This vector is in general very short. Optimize?
std::vector<GestureEventData> gestures_;
base::StackVector<GestureEventData, kTypicalMaxGesturesPerTouch> gestures_;
gfx::PointF touch_location_;
gfx::PointF raw_touch_location_;
GestureSource gesture_source_;
......
// Copyright 2014 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 "base/basictypes.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/events/gesture_detection/gesture_event_data_packet.h"
#include "ui/events/test/mock_motion_event.h"
using ui::test::MockMotionEvent;
namespace ui {
namespace {
const float kTouchX = 13.7f;
const float kTouchY = 14.2f;
GestureEventData CreateGesture(EventType type) {
return GestureEventData(GestureEventDetails(type, 0, 0),
0,
base::TimeTicks(),
kTouchX,
kTouchY,
kTouchX + 5.f,
kTouchY + 10.f,
1,
gfx::RectF(kTouchX - 1.f, kTouchY - 1.f, 2.f, 2.f));
}
} // namespace
bool GestureEquals(const GestureEventData& lhs, const GestureEventData& rhs) {
return lhs.type() == rhs.type() &&
lhs.motion_event_id == rhs.motion_event_id && lhs.time == rhs.time &&
lhs.x == rhs.x && lhs.y == rhs.y && lhs.raw_x == rhs.raw_x &&
lhs.raw_y == rhs.raw_y;
}
bool PacketEquals(const GestureEventDataPacket& lhs,
const GestureEventDataPacket& rhs) {
if (lhs.timestamp() != rhs.timestamp() ||
lhs.gesture_count() != rhs.gesture_count() ||
lhs.timestamp() != rhs.timestamp() ||
lhs.gesture_source() != rhs.gesture_source() ||
lhs.touch_location() != rhs.touch_location() ||
lhs.raw_touch_location() != rhs.raw_touch_location())
return false;
for (size_t i = 0; i < lhs.gesture_count(); ++i) {
if (!GestureEquals(lhs.gesture(i), rhs.gesture(i)))
return false;
}
return true;
}
class GestureEventDataPacketTest : public testing::Test {};
TEST_F(GestureEventDataPacketTest, Basic) {
base::TimeTicks touch_time = base::TimeTicks::Now();
GestureEventDataPacket packet;
EXPECT_EQ(0U, packet.gesture_count());
EXPECT_EQ(GestureEventDataPacket::UNDEFINED, packet.gesture_source());
packet = GestureEventDataPacket::FromTouch(
MockMotionEvent(MotionEvent::ACTION_DOWN, touch_time, kTouchX, kTouchY));
EXPECT_TRUE(touch_time == packet.timestamp());
EXPECT_EQ(0U, packet.gesture_count());
EXPECT_EQ(gfx::PointF(kTouchX, kTouchY), packet.touch_location());
for (size_t i = ET_GESTURE_TYPE_START; i < ET_GESTURE_TYPE_END; ++i) {
const EventType type = static_cast<EventType>(i);
GestureEventData gesture = CreateGesture(type);
packet.Push(gesture);
const size_t index = (i - ET_GESTURE_TYPE_START);
ASSERT_EQ(index + 1U, packet.gesture_count());
EXPECT_TRUE(GestureEquals(gesture, packet.gesture(index)));
}
}
TEST_F(GestureEventDataPacketTest, Copy) {
GestureEventDataPacket packet0 = GestureEventDataPacket::FromTouch(
MockMotionEvent(MotionEvent::ACTION_UP));
packet0.Push(CreateGesture(ET_GESTURE_TAP_DOWN));
packet0.Push(CreateGesture(ET_GESTURE_SCROLL_BEGIN));
GestureEventDataPacket packet1 = packet0;
EXPECT_TRUE(PacketEquals(packet0, packet1));
packet0 = packet1;
EXPECT_TRUE(PacketEquals(packet1, packet0));
}
TEST_F(GestureEventDataPacketTest, GestureSource) {
GestureEventDataPacket packet = GestureEventDataPacket::FromTouch(
MockMotionEvent(MotionEvent::ACTION_DOWN));
EXPECT_EQ(GestureEventDataPacket::TOUCH_SEQUENCE_START,
packet.gesture_source());
packet = GestureEventDataPacket::FromTouch(
MockMotionEvent(MotionEvent::ACTION_UP));
EXPECT_EQ(GestureEventDataPacket::TOUCH_SEQUENCE_END,
packet.gesture_source());
packet = GestureEventDataPacket::FromTouch(
MockMotionEvent(MotionEvent::ACTION_CANCEL));
EXPECT_EQ(GestureEventDataPacket::TOUCH_SEQUENCE_CANCEL,
packet.gesture_source());
packet = GestureEventDataPacket::FromTouch(
MockMotionEvent(MotionEvent::ACTION_MOVE));
EXPECT_EQ(GestureEventDataPacket::TOUCH_MOVE, packet.gesture_source());
packet = GestureEventDataPacket::FromTouch(
MockMotionEvent(MotionEvent::ACTION_POINTER_DOWN));
EXPECT_EQ(GestureEventDataPacket::TOUCH_START, packet.gesture_source());
packet = GestureEventDataPacket::FromTouch(
MockMotionEvent(MotionEvent::ACTION_POINTER_UP));
EXPECT_EQ(GestureEventDataPacket::TOUCH_END, packet.gesture_source());
GestureEventData gesture = CreateGesture(ET_GESTURE_TAP);
packet = GestureEventDataPacket::FromTouchTimeout(gesture);
EXPECT_EQ(GestureEventDataPacket::TOUCH_TIMEOUT, packet.gesture_source());
EXPECT_EQ(1U, packet.gesture_count());
EXPECT_EQ(base::TimeTicks(), packet.timestamp());
EXPECT_EQ(gfx::PointF(gesture.x, gesture.y), packet.touch_location());
}
} // namespace ui
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment