| 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 db190c76b9d2d5ab8b337573f31b3ffb04dad04e..ef9b08ec75efb2ac74a52e51511148d0f94c7461 100644
|
| --- a/chrome/test/base/interactive_test_utils_mac.mm
|
| +++ b/chrome/test/base/interactive_test_utils_mac.mm
|
| @@ -7,65 +7,16 @@
|
| #include <Carbon/Carbon.h>
|
| #import <Cocoa/Cocoa.h>
|
|
|
| -#include "base/threading/simple_thread.h"
|
| -#include "base/threading/thread_task_runner_handle.h"
|
| #include "chrome/app/chrome_command_ids.h"
|
| #include "chrome/browser/ui/views/tabs/window_finder.h"
|
| #import "ui/base/test/windowed_nsnotification_observer.h"
|
| #include "ui/gfx/animation/tween.h"
|
| -#include "ui/gfx/mac/coordinate_conversion.h"
|
| -#include "ui/views/cocoa/bridged_native_widget.h"
|
| -#include "ui/views/event_monitor.h"
|
| -#include "ui/views/widget/native_widget_mac.h"
|
|
|
| -namespace {
|
| -
|
| -bool WaitForEvent(bool (^block)(const base::Closure& quit_closure)) {
|
| - base::RunLoop runner;
|
| - bool result = block(runner.QuitClosure());
|
| - runner.Run();
|
| - return result;
|
| -}
|
| -
|
| -bool MouseMove(const gfx::Point& p,
|
| - const base::TimeDelta& delay = base::TimeDelta()) {
|
| - if (!delay.is_zero()) {
|
| - bool result =
|
| - ui_controls::SendMouseMoveNotifyWhenDone(p.x(), p.y(), base::Closure());
|
| - usleep(delay.InMicroseconds());
|
| - return result;
|
| - }
|
| -
|
| - return WaitForEvent(^(const base::Closure& quit_closure) {
|
| - return ui_controls::SendMouseMoveNotifyWhenDone(p.x(), p.y(), quit_closure);
|
| - });
|
| -}
|
| -
|
| -bool MouseDown() {
|
| - return WaitForEvent(^(const base::Closure& quit_closure) {
|
| - return ui_controls::SendMouseEventsNotifyWhenDone(
|
| - ui_controls::LEFT, ui_controls::DOWN, quit_closure);
|
| - });
|
| -}
|
| -
|
| -bool MouseUp() {
|
| - return WaitForEvent(^(const base::Closure& quit_closure) {
|
| - return ui_controls::SendMouseEventsNotifyWhenDone(
|
| - ui_controls::LEFT, ui_controls::UP, quit_closure);
|
| - });
|
| -}
|
| +namespace ui_test_utils {
|
|
|
| -std::vector<ui_test_utils::DragAndDropOperation> DragAndDropMoveOperations(
|
| - const std::list<ui_test_utils::DragAndDropOperation>& operations) {
|
| - std::vector<ui_test_utils::DragAndDropOperation> move_operations;
|
| - std::copy_if(operations.begin(), operations.end(),
|
| - std::back_inserter(move_operations),
|
| - [](const ui_test_utils::DragAndDropOperation& op) {
|
| - return op.type() == ui_test_utils::DragAndDropOperation::Type::Move;
|
| - });
|
| - return move_operations;
|
| -}
|
| +namespace {
|
|
|
| +// comment
|
| class ScopedCGEventsEnabler {
|
| public:
|
| ScopedCGEventsEnabler()
|
| @@ -81,108 +32,75 @@ class ScopedCGEventsEnabler {
|
| bool enable_cgevents_;
|
| };
|
|
|
| -class BlockRunner : public base::DelegateSimpleThread::Delegate {
|
| +// comment
|
| +class OperationRunner {
|
| public:
|
| - BlockRunner(void (^block)(), const base::Closure& quit_closure)
|
| - : block_(block),
|
| - quit_closure_(quit_closure),
|
| - task_runner_(base::ThreadTaskRunnerHandle::Get()) {}
|
| - ~BlockRunner() override {}
|
| -
|
| - void Run() override {
|
| - std::unique_ptr<base::MessageLoop> loop(
|
| - new base::MessageLoop(base::MessageLoop::TYPE_DEFAULT));
|
| -
|
| - block_();
|
| -
|
| - task_runner_->PostTask(FROM_HERE, quit_closure_);
|
| + static void Run(const std::list<DragAndDropOperation>& operations) {
|
| + OperationRunner runner(operations);
|
| + base::RunLoop run_loop;
|
| + runner.quit_closure_ = run_loop.QuitClosure();
|
| + base::MessageLoop::current()->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&OperationRunner::Next, base::Unretained(&runner)));
|
| + run_loop.Run();
|
| }
|
|
|
| private:
|
| - void (^block_)();
|
| - base::Closure quit_closure_;
|
| - scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
|
| -};
|
| -
|
| -void RunAtBackgroundQueue(void (^block)()) {
|
| - DCHECK_EQ(dispatch_get_current_queue(), dispatch_get_main_queue());
|
| - base::RunLoop runner;
|
| + explicit OperationRunner(const std::list<DragAndDropOperation>& operations)
|
| + : operations_(operations.begin(), operations.end()) {}
|
|
|
| - BlockRunner thread_runner(block, runner.QuitClosure());
|
| - base::DelegateSimpleThread thread(&thread_runner,
|
| - "interactive_test_utils.BackgroundQueue");
|
| - thread.Start();
|
| -
|
| - // We need to run the loop on the main thread, so the mouse events will be
|
| - // actually processed.
|
| - runner.Run();
|
| -
|
| - thread.Join();
|
| -}
|
| + void Next() {
|
| + if (progress_ == operations_.size()) {
|
| + base::MessageLoop::current()->PostTask(FROM_HERE, quit_closure_);
|
| + return;
|
| + }
|
|
|
| -bool WindowIsMoving(NSWindow* window) {
|
| - views::BridgedNativeWidget* bridge =
|
| - views::NativeWidgetMac::GetBridgeForNativeWindow(window);
|
| - DCHECK(bridge);
|
| - return bridge->IsRunMoveLoopActive();
|
| -}
|
| + const DragAndDropOperation& op = operations_[progress_++];
|
| + 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;
|
| +
|
| + case DragAndDropOperation::Type::SetMousePositionOverride:
|
| + ui_controls::SetMousePositionOverride(true, op.point());
|
| + base::MessageLoop::current()->PostTask(FROM_HERE, next);
|
| + break;
|
| +
|
| + case DragAndDropOperation::Type::UnsetMousePositionOverride:
|
| + ui_controls::SetMousePositionOverride(false, gfx::Point());
|
| + base::MessageLoop::current()->PostTask(FROM_HERE, next);
|
| + break;
|
| +
|
| + case DragAndDropOperation::Type::DebugDelay:
|
| + base::MessageLoop::current()->PostDelayedTask(
|
| + FROM_HERE, next, base::TimeDelta::FromSeconds(1));
|
| + break;
|
| + }
|
| + }
|
|
|
| -// Returns true if window under the cursor is currently moving by WindowServer.
|
| -bool WindowIsMovingBySystem() {
|
| - NSWindow* window = WindowFinder().GetLocalProcessWindowAtPoint(
|
| - views::EventMonitor::GetLastMouseLocation(),
|
| - std::set<gfx::NativeWindow>());
|
| - return window && WindowIsMoving(window);
|
| -}
|
| + ~OperationRunner() { DCHECK_EQ(operations_.size(), progress_); }
|
|
|
| -// If current window under the cursor is currently moving by WindowServer, wait
|
| -// for the NSWindowMovedEventType notification.
|
| -//
|
| -// Returns whether the window under the cursor was moved by the system.
|
| -bool WaitForSystemWindowMoveToStop() {
|
| - // NOTE: This is a potentially troublesome part, currently it only works
|
| - // with MacViewsBrowser when the moved window entered RunMoveLoop.
|
| - // On non-MacViewsBrowser builds or when the window was moved using the
|
| - // caption we would be unable to detect that the window was moved using the
|
| - // WindowServer and would not wait for the final NSWindowMovedEventType
|
| - // notification.
|
| - //
|
| - // As a possible solution it would be possible to add an
|
| - // additional argument to the function
|
| - // |force_wait_for_system_window_move_to_finish|, and force waiting for
|
| - // notification if this ever becomes a problem.
|
| - NSWindow* window = WindowFinder().GetLocalProcessWindowAtPoint(
|
| - views::EventMonitor::GetLastMouseLocation(),
|
| - std::set<gfx::NativeWindow>());
|
| - const bool window_is_moving_by_system = window && WindowIsMoving(window);
|
| -
|
| - if (WindowIsMovingBySystem()) {
|
| - // Wait for a final NSWindowMovedEventType notification, otherwise
|
| - // the window won't be in the final position. It arrives asynchronously
|
| - // after the mouse move events.
|
| - NSEvent* window_move_event =
|
| - [NSEvent otherEventWithType:NSAppKitDefined
|
| - location:NSZeroPoint
|
| - modifierFlags:0
|
| - timestamp:0
|
| - windowNumber:0
|
| - context:0
|
| - subtype:NSWindowMovedEventType
|
| - data1:0
|
| - data2:0];
|
| - base::RunLoop no_window_move_runner;
|
| - ui_controls::NotifyWhenEventIsProcessed(
|
| - window_move_event, no_window_move_runner.QuitClosure());
|
| - no_window_move_runner.Run();
|
| - }
|
| + base::Closure quit_closure_;
|
| + size_t progress_ = 0;
|
| + std::vector<DragAndDropOperation> operations_;
|
|
|
| - return window_is_moving_by_system;
|
| -}
|
| + DISALLOW_COPY_AND_ASSIGN(OperationRunner);
|
| +};
|
|
|
| } // namespace
|
|
|
| -namespace ui_test_utils {
|
| -
|
| void HideNativeWindow(gfx::NativeWindow window) {
|
| [window orderOut:nil];
|
| }
|
| @@ -215,60 +133,8 @@ bool ShowAndFocusNativeWindow(gfx::NativeWindow window) {
|
| }
|
|
|
| void DragAndDrop(const std::list<DragAndDropOperation>& operations) {
|
| - const bool should_be_moved_by_system =
|
| - DragAndDropMoveOperations(operations).size() > 2;
|
| -
|
| ScopedCGEventsEnabler cgevents_enabler;
|
| -
|
| - RunAtBackgroundQueue(^() {
|
| - std::list<DragAndDropOperation> mutable_operations(operations);
|
| - bool window_was_moved_by_system = false;
|
| -
|
| - while (!mutable_operations.empty()) {
|
| - DragAndDropOperation op = mutable_operations.front();
|
| - mutable_operations.pop_front();
|
| - const bool last_operation = mutable_operations.empty();
|
| - const bool have_remaining_move_operations =
|
| - !DragAndDropMoveOperations(mutable_operations).empty();
|
| -
|
| - switch (op.type()) {
|
| - case DragAndDropOperation::Type::Move:
|
| - case DragAndDropOperation::Type::MoveWithoutAck:
|
| - MouseMove(op.point(), op.delay());
|
| - // During the drag a new window could be both detached and reattached,
|
| - // and if we check for WindowIsMovingBySystem() only at the very end,
|
| - // it will return false, as the original window was stationary.
|
| - window_was_moved_by_system |= WindowIsMovingBySystem();
|
| -
|
| - if (!have_remaining_move_operations) {
|
| - // WaitForSystemWindowMoveToStop() is necessary to make sure window
|
| - // frame is final after the drag-n-drop operation.
|
| - window_was_moved_by_system |= WaitForSystemWindowMoveToStop();
|
| - DCHECK_EQ(window_was_moved_by_system, should_be_moved_by_system);
|
| - }
|
| - break;
|
| - case DragAndDropOperation::Type::MouseDown:
|
| - MouseDown();
|
| - break;
|
| - case DragAndDropOperation::Type::MouseUp:
|
| - MouseUp();
|
| -
|
| - if (last_operation) {
|
| - DCHECK(!WindowIsMovingBySystem());
|
| - }
|
| - break;
|
| - case DragAndDropOperation::Type::SetMousePositionOverride:
|
| - ui_controls::SetMousePositionOverride(true, op.point());
|
| - break;
|
| - case DragAndDropOperation::Type::UnsetMousePositionOverride:
|
| - ui_controls::SetMousePositionOverride(false, gfx::Point());
|
| - break;
|
| - case DragAndDropOperation::Type::DebugDelay:
|
| - usleep(op.delay().InMicroseconds());
|
| - break;
|
| - }
|
| - }
|
| - });
|
| + OperationRunner::Run(operations);
|
| }
|
|
|
| void DragAndDrop(const gfx::Point& from, const gfx::Point& to, int steps) {
|
| @@ -294,13 +160,6 @@ DragAndDropOperation DragAndDropOperation::Move(const gfx::Point& p) {
|
| }
|
|
|
| // static
|
| -DragAndDropOperation DragAndDropOperation::MoveWithoutAck(
|
| - const gfx::Point& p,
|
| - const base::TimeDelta& delay) {
|
| - return DragAndDropOperation(Type::MoveWithoutAck, p, delay);
|
| -}
|
| -
|
| -// static
|
| DragAndDropOperation DragAndDropOperation::MouseDown() {
|
| return DragAndDropOperation(Type::MouseDown, gfx::Point());
|
| }
|
| @@ -323,8 +182,7 @@ DragAndDropOperation DragAndDropOperation::UnsetMousePositionOverride() {
|
|
|
| // static
|
| DragAndDropOperation DragAndDropOperation::DebugDelay() {
|
| - return DragAndDropOperation(Type::DebugDelay, gfx::Point(),
|
| - base::TimeDelta::FromSeconds(1));
|
| + return DragAndDropOperation(Type::DebugDelay, gfx::Point());
|
| }
|
|
|
| } // namespace ui_test_utils
|
|
|