blob: de123aa24307a064beb9b098e7a5d27d99263e64 [file] [log] [blame]
// 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 "ui/events/test/motion_event_test_utils.h"
#include <sstream>
#include "base/logging.h"
#include "ui/events/base_event_utils.h"
#include "ui/events/gesture_detection/bitset_32.h"
#include "ui/events/gesture_detection/motion_event.h"
using base::TimeTicks;
namespace ui {
namespace test {
namespace {
PointerProperties CreatePointer() {
PointerProperties pointer;
pointer.touch_major = MockMotionEvent::TOUCH_MAJOR;
return pointer;
}
PointerProperties CreatePointer(float x, float y, int id) {
PointerProperties pointer(x, y, MockMotionEvent::TOUCH_MAJOR);
pointer.id = id;
return pointer;
}
} // namespace
MockMotionEvent::MockMotionEvent()
: MotionEventGeneric(Action::CANCEL, base::TimeTicks(), CreatePointer()) {}
MockMotionEvent::MockMotionEvent(Action action)
: MotionEventGeneric(action, base::TimeTicks(), CreatePointer()) {
}
MockMotionEvent::MockMotionEvent(Action action,
TimeTicks time,
float x0,
float y0)
: MotionEventGeneric(action, time, CreatePointer(x0, y0, 0)) {
}
MockMotionEvent::MockMotionEvent(Action action,
TimeTicks time,
float x0,
float y0,
float x1,
float y1)
: MotionEventGeneric(action, time, CreatePointer(x0, y0, 0)) {
PushPointer(x1, y1);
if (action == Action::POINTER_UP || action == Action::POINTER_DOWN)
set_action_index(1);
}
MockMotionEvent::MockMotionEvent(Action action,
TimeTicks time,
float x0,
float y0,
float x1,
float y1,
float x2,
float y2)
: MotionEventGeneric(action, time, CreatePointer(x0, y0, 0)) {
PushPointer(x1, y1);
PushPointer(x2, y2);
if (action == Action::POINTER_UP || action == Action::POINTER_DOWN)
set_action_index(2);
}
MockMotionEvent::MockMotionEvent(Action action,
base::TimeTicks time,
const std::vector<gfx::PointF>& positions) {
set_action(action);
set_event_time(time);
set_unique_event_id(ui::GetNextTouchEventId());
if (action == Action::POINTER_UP || action == Action::POINTER_DOWN)
set_action_index(static_cast<int>(positions.size()) - 1);
for (size_t i = 0; i < positions.size(); ++i)
PushPointer(positions[i].x(), positions[i].y());
}
MockMotionEvent::MockMotionEvent(const MockMotionEvent& other)
: MotionEventGeneric(other) {
}
MockMotionEvent::~MockMotionEvent() {
}
MockMotionEvent& MockMotionEvent::PressPoint(float x, float y) {
UpdatePointersAndID();
PushPointer(x, y);
if (GetPointerCount() > 1) {
set_action_index(static_cast<int>(GetPointerCount()) - 1);
set_action(Action::POINTER_DOWN);
} else {
set_action(Action::DOWN);
}
return *this;
}
MockMotionEvent& MockMotionEvent::MovePoint(size_t index, float x, float y) {
UpdatePointersAndID();
DCHECK_LT(index, GetPointerCount());
PointerProperties& p = pointer(index);
float dx = x - p.x;
float dy = x - p.y;
p.x = x;
p.y = y;
p.raw_x += dx;
p.raw_y += dy;
set_action(Action::MOVE);
return *this;
}
MockMotionEvent& MockMotionEvent::ReleasePoint() {
DCHECK_GT(GetPointerCount(), 0U);
switch (GetAction()) {
// If the previous action is one of those who need removing a pointer in
// UpdatePointersAndID, then the last index will be GetPointerCount() - 2.
case Action::POINTER_UP:
case Action::UP:
case Action::CANCEL:
return ReleasePointAtIndex(GetPointerCount() - 2);
break;
default:
break;
}
return ReleasePointAtIndex(GetPointerCount() - 1);
}
MockMotionEvent& MockMotionEvent::ReleasePointAtIndex(size_t index) {
UpdatePointersAndID();
DCHECK_LT(index, GetPointerCount());
if (GetPointerCount() > 1) {
set_action_index(static_cast<int>(index));
set_action(Action::POINTER_UP);
} else {
set_action(Action::UP);
}
return *this;
}
MockMotionEvent& MockMotionEvent::CancelPoint() {
UpdatePointersAndID();
DCHECK_GT(GetPointerCount(), 0U);
set_action(Action::CANCEL);
return *this;
}
MockMotionEvent& MockMotionEvent::SetTouchMajor(float new_touch_major) {
for (size_t i = 0; i < GetPointerCount(); ++i)
pointer(i).touch_major = new_touch_major;
return *this;
}
MockMotionEvent& MockMotionEvent::SetRawOffset(float raw_offset_x,
float raw_offset_y) {
for (size_t i = 0; i < GetPointerCount(); ++i) {
pointer(i).raw_x = pointer(i).x + raw_offset_x;
pointer(i).raw_y = pointer(i).y + raw_offset_y;
}
return *this;
}
MockMotionEvent& MockMotionEvent::SetToolType(size_t pointer_index,
ToolType tool_type) {
DCHECK_LT(pointer_index, GetPointerCount());
pointer(pointer_index).tool_type = tool_type;
return *this;
}
void MockMotionEvent::PushPointer(float x, float y) {
MotionEventGeneric::PushPointer(
CreatePointer(x, y, static_cast<int>(GetPointerCount())));
}
void MockMotionEvent::UpdatePointersAndID() {
set_unique_event_id(ui::GetNextTouchEventId());
switch (GetAction()) {
case Action::POINTER_UP: {
int index = GetActionIndex();
DCHECK_LT(index, static_cast<int>(GetPointerCount()));
RemovePointerAt(index);
break;
}
case Action::UP:
case Action::CANCEL:
PopPointer();
break;
default:
break;
}
set_action_index(-1);
}
MockMotionEvent& MockMotionEvent::SetPrimaryPointerId(int id) {
DCHECK_GT(GetPointerCount(), 0U);
pointer(0).id = id;
return *this;
}
std::string ToString(const MotionEvent& event) {
std::stringstream ss;
ss << "MotionEvent {"
<< "\n Action: " << event.GetAction();
if (event.GetAction() == MotionEvent::Action::POINTER_DOWN ||
event.GetAction() == MotionEvent::Action::POINTER_UP)
ss << "\n ActionIndex: " << event.GetActionIndex();
ss << "\n Flags: " << event.GetFlags()
<< "\n ButtonState: " << event.GetButtonState() << "\n Pointers: [";
const size_t pointer_count = event.GetPointerCount();
const size_t history_size = event.GetHistorySize();
BitSet32 pointer_ids;
for (size_t i = 0; i < pointer_count; ++i) {
pointer_ids.mark_bit(event.GetPointerId(i));
// Print the pointers sorted by id.
while (!pointer_ids.is_empty()) {
int pi = event.FindPointerIndexOfId(pointer_ids.first_marked_bit());
DCHECK_GE(pi, 0);
pointer_ids.clear_first_marked_bit();
ss << "{"
<< "\n PointerId: (" << event.GetPointerId(pi) << ")"
<< "\n Pos: (" << event.GetX(pi) << ", " << event.GetY(pi) << ")"
<< "\n RawPos: (" << event.GetX(pi) << ", " << event.GetY(pi) << ")"
<< "\n Size: (" << event.GetTouchMajor(pi) << ", "
<< event.GetTouchMinor(pi) << ")"
<< "\n Orientation: " << event.GetOrientation(pi)
<< "\n Pressure: " << event.GetPressure(pi)
<< "\n TiltX: " << event.GetTiltX(pi)
<< "\n TiltY: " << event.GetTiltY(pi)
<< "\n Tool: " << event.GetToolType(pi);
if (history_size) {
ss << "\n History: [";
for (size_t h = 0; h < history_size; ++h) {
ss << "\n { " << event.GetHistoricalX(pi, h) << ", "
<< event.GetHistoricalY(pi, h) << ", "
<< event.GetHistoricalTouchMajor(pi, h) << ", "
<< event.GetHistoricalEventTime(pi) << " }";
if (h + 1 < history_size)
ss << ",";
}
ss << "\n ]";
}
ss << "\n }";
if (i + 1 < pointer_count)
ss << ", ";
}
ss << "]\n}";
}
return ss.str();
}
} // namespace test
} // namespace ui