| Index: chrome/test/base/interactive_test_utils_mac.mm
|
| diff --git a/chrome/test/base/interactive_test_utils_mac.mm b/chrome/test/base/interactive_test_utils_mac.mm
|
| index 0d00f3a6614e3aacd4c9141ed971ae02590ea1d1..a1db4aa7d54aea38b2c77dd9558df672b872993b 100644
|
| --- a/chrome/test/base/interactive_test_utils_mac.mm
|
| +++ b/chrome/test/base/interactive_test_utils_mac.mm
|
| @@ -7,12 +7,109 @@
|
| #include <Carbon/Carbon.h>
|
| #import <Cocoa/Cocoa.h>
|
|
|
| -#include "base/message_loop/message_loop.h"
|
| +#include "base/threading/thread_task_runner_handle.h"
|
| #include "chrome/app/chrome_command_ids.h"
|
| #import "ui/base/test/windowed_nsnotification_observer.h"
|
| +#include "ui/gfx/animation/tween.h"
|
|
|
| namespace ui_test_utils {
|
|
|
| +namespace {
|
| +
|
| +// Runs a list of drag and drop |operations| on a single RunLoop.
|
| +//
|
| +// We need to execute drag and drop operations as a batch, so the nested
|
| +// RunMoveLoop()'s RunLoop is cancelled before the top-level one from which we
|
| +// post the simulated events, otherwise we'll deadlock.
|
| +class OperationRunner {
|
| + public:
|
| + static void Run(const std::list<DragAndDropOperation>& operations) {
|
| + OperationRunner runner(operations);
|
| + base::RunLoop run_loop;
|
| + runner.quit_closure_ = run_loop.QuitClosure();
|
| + base::ThreadTaskRunnerHandle::Get()->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&OperationRunner::Next, base::Unretained(&runner)));
|
| + run_loop.Run();
|
| + }
|
| +
|
| + private:
|
| + explicit OperationRunner(const std::list<DragAndDropOperation>& operations)
|
| + : operations_(operations) {}
|
| +
|
| + void Next() {
|
| + if (operations_.empty()) {
|
| + base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, quit_closure_);
|
| + return;
|
| + }
|
| +
|
| + const DragAndDropOperation op = operations_.front();
|
| + operations_.pop_front();
|
| + auto next = base::Bind(&OperationRunner::Next, base::Unretained(this));
|
| + switch (op.type()) {
|
| + case DragAndDropOperation::Type::Move:
|
| + ui_controls::SendMouseMoveNotifyWhenDone(op.point().x(), op.point().y(),
|
| + next);
|
| + break;
|
| +
|
| + case DragAndDropOperation::Type::MouseDown:
|
| + ui_controls::SendMouseEventsNotifyWhenDone(ui_controls::LEFT,
|
| + ui_controls::DOWN, next);
|
| + break;
|
| +
|
| + case DragAndDropOperation::Type::MouseUp:
|
| + ui_controls::SendMouseEventsNotifyWhenDone(ui_controls::LEFT,
|
| + ui_controls::UP, next);
|
| + break;
|
| + }
|
| + }
|
| +
|
| + ~OperationRunner() { DCHECK(operations_.empty()); }
|
| +
|
| + base::Closure quit_closure_;
|
| + std::list<DragAndDropOperation> operations_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(OperationRunner);
|
| +};
|
| +
|
| +} // namespace
|
| +
|
| +// static
|
| +DragAndDropOperation DragAndDropOperation::Move(const gfx::Point& p) {
|
| + return DragAndDropOperation(Type::Move, p);
|
| +}
|
| +
|
| +// static
|
| +DragAndDropOperation DragAndDropOperation::MouseDown() {
|
| + return DragAndDropOperation(Type::MouseDown, gfx::Point());
|
| +}
|
| +
|
| +// static
|
| +DragAndDropOperation DragAndDropOperation::MouseUp() {
|
| + return DragAndDropOperation(Type::MouseUp, gfx::Point());
|
| +}
|
| +
|
| +void DragAndDropSequence(const std::list<DragAndDropOperation>& operations) {
|
| + OperationRunner::Run(operations);
|
| +}
|
| +
|
| +void DragAndDrop(const gfx::Point& from, const gfx::Point& to, int steps) {
|
| + DCHECK_GE(steps, 1);
|
| + std::list<DragAndDropOperation> operations;
|
| + operations.push_back(DragAndDropOperation::Move(from));
|
| + operations.push_back(DragAndDropOperation::MouseDown());
|
| +
|
| + for (int i = 1; i <= steps; ++i) {
|
| + const double progress = static_cast<double>(i) / steps;
|
| + operations.push_back(DragAndDropOperation::Move(
|
| + gfx::Point(gfx::Tween::IntValueBetween(progress, from.x(), to.x()),
|
| + gfx::Tween::IntValueBetween(progress, from.y(), to.y()))));
|
| + }
|
| +
|
| + operations.push_back(DragAndDropOperation::MouseUp());
|
| + DragAndDropSequence(operations);
|
| +}
|
| +
|
| void HideNativeWindow(gfx::NativeWindow window) {
|
| [window orderOut:nil];
|
| }
|
|
|